home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr50 / langwn23.zip / WINHELP.BAS < prev   
BASIC Source File  |  1993-02-11  |  108KB  |  2,823 lines

  1. DEFINT A-Z
  2.  
  3. ' ONLINE HELP FOR LANGWIN ROUTINES
  4.  
  5. ' Hit F2 to see list of routines
  6. ' (same names as LangWin routines,
  7. ' except corresponding help routines end with a period).
  8.  
  9.  
  10. ' The following routines are documented:
  11. DECLARE FUNCTION ActivateButton. ()
  12. DECLARE FUNCTION BlankWin. ()
  13. DECLARE SUB ChangeButtonFocus. ()
  14. DECLARE FUNCTION ChangeDir. ()
  15. DECLARE FUNCTION ChangeDrive. ()
  16. DECLARE FUNCTION CloseWindow. ()
  17. DECLARE FUNCTION DeactivateButton. ()
  18. DECLARE SUB GetButtonPress. ()
  19. DECLARE FUNCTION GetCurDir.$ ()
  20. DECLARE FUNCTION GetCurDrive.$ ()
  21. DECLARE FUNCTION GetFileNames. ()
  22. DECLARE SUB GetMousePos. ()
  23. DECLARE FUNCTION GetVerNum.$ ()
  24. DECLARE FUNCTION GrowScrollText. ()
  25. DECLARE SUB HideMouseCursor. ()
  26. DECLARE FUNCTION InitMouse. ()
  27. DECLARE FUNCTION IsWinOpen. ()
  28. DECLARE SUB LangWinInit. ()
  29. DECLARE FUNCTION MakeBox. ()
  30. DECLARE FUNCTION MakeCheckBox. ()
  31. DECLARE FUNCTION MakeHorizLine. ()
  32. DECLARE FUNCTION MakeInputField. ()
  33. DECLARE FUNCTION MakePushButton. ()
  34. DECLARE FUNCTION MakeVertLine. ()
  35. DECLARE FUNCTION MouseExists. ()
  36. DECLARE SUB NewFocusWindow. ()
  37. DECLARE FUNCTION OpenScrollWindow. ()
  38. DECLARE SUB RefreshScrollText. ()
  39. DECLARE SUB ReShowInputField. ()
  40. DECLARE SUB ReShowPage. ()
  41. DECLARE SUB ReShowText. ()
  42. DECLARE SUB SetColor. ()
  43. DECLARE SUB SetMousePos. ()
  44. DECLARE SUB SetXLimit. ()
  45. DECLARE SUB SetYLimit. ()
  46. DECLARE SUB ShowMouseCursor. ()
  47. DECLARE FUNCTION ShowTitle. ()
  48. DECLARE FUNCTION ShowWinText. ()
  49. DECLARE SUB WaitTicks. ()
  50. DECLARE FUNCTION WinEvent. ()
  51.  
  52. END
  53.  
  54. FUNCTION ActivateButton.
  55.  
  56. 'Purpose:
  57. '--------
  58. '   Activate a button by restoring its text.
  59. '   When the button was deactivated (see DeactivateButton function),
  60. '   it's text was cleared and WinEvent no longer recognized clicks on
  61. '   the button. This function is used to reset the text so that WinEvent
  62. '   will recognize it and user can again click the button.
  63.  
  64. '   Window containing the button will be given focus before the
  65. '   button's text is restored. User has option whether or not
  66. '   to return focus to the window that was current when ActivateButton
  67. '   was called.
  68.  
  69. '   (New with V2.0)
  70. '   (Button's text no longer needed as a parameter with V2.1)
  71.  
  72. 'Routine Type:
  73. '-------------
  74. '  Function.
  75.  
  76.  
  77.  
  78. 'Parameters:
  79. '-----------
  80. '  ButtonHandle   - handle of button to be activated
  81.  
  82. '  FocusSw        - switch to determine if window that was current when
  83. '                   ActivateButton was called should be given focus back
  84. '                   after button has been activated. ActivateButton WILL
  85. '                   give focus to the window containing the button before
  86. '                   it updates the text. This could produce one change in
  87. '                   focus (depending on which window had focus when function
  88. '                   was called). After the button has been activated, you can
  89. '                   either leave focus in the window containing the button,
  90. '                   or give focus back to the original window (may produce
  91. '                   another focus change on screen). See Notes below for
  92. '                   more details on using this parameter.
  93.  
  94. '                   = 0    do not change focus back to original
  95. '                   = 1    change focus back to original window
  96. '
  97.  
  98.  
  99.  
  100. '
  101. 'Return Values:
  102. '--------------
  103. ' 0   - button successfully activated
  104. ' 1   - ButtonHandle was not within index range
  105. '       of ButtonsData array. Typically, ButtonHandle
  106. '       should be between 1 and MaxButtons.
  107. ' 2   - ButtonHandle was within range, but it did
  108. '       not have a corresponding open window. This
  109. '       probably means ButtonHandle was incorrect.
  110. ' 3   - ButtonHandle did not correspond to a push
  111. '       button.
  112.  
  113.  
  114. 'Notes:
  115. '------
  116. '   With LangWin V2.1, the text of the button being activated is no longer
  117. '   required as an input parameter. The button's original text is remembered
  118. '   when it is deactivated, and will automatically be displayed when the
  119. '   button is activated. If you used the string passed to the V2.0 version
  120. '   ActivateButton to change the button's text, then you must now update
  121. '   the contents of ButtonsText(han) instead, where han is the button's
  122. '   handle. In this case, do not place a string into ButtonsText that
  123. '   exceeds the button's length which is found in ButtonsData(han,4).
  124.  
  125.  
  126. '   Some comments on the use of the FocusSw parameter:
  127. '   Typically, ActivateButton is called just after closing a child window to
  128. '   re-activate a button in the parent window. In this case, you cannot be
  129. '   sure the parent window had focus when you call ActivateButton (after
  130. '   closing the child). The close routine gives focus to the next window on
  131. '   the stack (which can change dynamically depending upon what window the
  132. '   user clicked last before closing the child). If the parent was not the
  133. '   last window on the stack, then ActivateButton will have caused one
  134. '   change in focus (it automatically gives focus to the window with the
  135. '   given button before changing its text). Thus, leaving focus in the window
  136. '   with the button (i.e., the parent) will be less disruptive visually.
  137. '   Call ActivateButton with the FocusSw set to 0 to leave focus in window
  138. '   with the given button.
  139.  
  140.  
  141. END FUNCTION
  142.  
  143. FUNCTION BlankWin.
  144.  
  145. 'Purpose:
  146. '--------
  147. '  Open/display an empty window.
  148. '  New window is given focus.
  149. '
  150. '
  151. 'Routine Type:
  152. '-------------
  153. '  Function.
  154. '
  155. '
  156. 'V2.0 Changes:
  157. '-------------
  158. '  Negative value for WinColor% will make window unmovable.
  159. '  New ModeSw% parameter required.
  160. '  Negative value for ModeSw% will make window shadowless.
  161. '  Return values changed:
  162. '    Negative value returned if window not opened successfully.
  163. '    Window's number (>0) returned if window is opened successfully.
  164. '    0 is not a valid return code.
  165. '    -12 is a new return code.
  166.  
  167. 'Parameters:
  168. '-----------
  169. '  StartRow%:    starting row (upper left)
  170. '  StartCol%:    starting column (upper left)
  171. '  EndRow%:      ending row (bottom right)
  172. '  EndCol%:      ending column (bottom right)
  173. '  WinColor%:    color attribute of window (0-15)
  174. '                (NEGATIVE value will make window unmovable)
  175. '  BorderColor%: color attribute of border (0-15)
  176. '                (NEGATIVE value will prevent window from being resized)
  177. '  BorderType%:  1=single line; 2=double line
  178. '  TextColor%:   color attribute for scrollable text in the window (0-15)
  179. '                (since BlankWin has no scrollable text, this attribute
  180. '                is only used for the close icon if present)
  181. '  CloseIcon%:   1=display a close icon; 0=no close icon
  182. '                [regardless of whether a close icon is displayed, the ESC
  183. '                key will always generate a close action]
  184. '                [cannot specify a close icon for a window with ModeSw=4]
  185. '  ModeSw%       Mode of window (effects how/if/when WinEvent returns
  186. '                control after an action has taken place)
  187. '                (NEGATIVE value for mode will generate a shadowless window):
  188. '                1 = modeless window (normal). if modeless window has
  189. '                    focus, user can click on any other visible window
  190. '                    and it will be given focus by WinEvent. WinEvent will
  191. '                    continue to process the new window until an action
  192. '                    is taken in the current window.
  193. '                2 = modal window. if modal window has focus, any attempt
  194. '                    to click on another window will be ignored by WinEvent.
  195. '                    this type of window can be used to display a message,
  196. '                    and force user to close the window before continuing
  197. '                    (e.g., for error messages).
  198. '                3 = immediate close window. if this type window has focus,
  199. '                    clicking on another window, or even the wallpaper, will
  200. '                    cause WinEvent to return a close action (1). This can be
  201. '                    used for menu windows that should be closed if user
  202. '                    clicks somewhere else on the screen.
  203. '                4 = wallpaper window. can never be selected, only serves as
  204. '                    background for other windows (usually of same color
  205. '                    as the wallpaper window). since wallpaper windows can
  206. '                    never be given focus, they should not be given any
  207. '                    objects (buttons, etc) and cannot have a close icon.
  208.  
  209. 'Return Values:
  210. '--------------
  211. ' >0:  window opened successfully (win number returned)
  212. ' -1:  not enough storage to open another new window.
  213. '      [must increase value of MaxWindows global parameter]
  214. ' -2:  not enough room for window's rows (+1 for shadow) on screen
  215. ' -3:  not enough room for window's columns (+2 for shadow) on screen
  216. ' -4:  window's color attribute out of range (must be 0-15)
  217. ' -5:  window's border color attribute out of range (must be 0-15)
  218. ' -6:  invalid value for BorderType (must be -1 or -2)
  219. ' -7:  text color attribute out of range (must be 0-15)
  220. ' -8:  window not long enough (must be >=3)
  221. ' -9:  window not wide enough (must be >=3)
  222. '-10:  [not used]
  223. '-11:  [not used]
  224. '-12:  invalid value for window mode (ModeSw) - must be 1 to 4
  225. '
  226.  
  227. 'Notes:
  228. '------
  229. '  You MUST check to see if window opened successfully (return code>0)
  230. '  before calling any other LangWin functions or routines.
  231. '  Otherwise, you will either get errors (such as Illegal Function Call,
  232. '  Subscript Out of Range, etc.) or process the previously opened window
  233. '  by mistake.
  234.  
  235. '  BlankWin sets the global variable AnyWinOpen to TRUE.
  236. '  this can be used to control a DO/LOOP that executes WinEvent
  237. '  as long as there is an open window on the screen. However, if an
  238. '  information only window is open, then you must use another criteria to
  239. '  end the DO/LOOP because the info only window will always be open.
  240. '  In this case, termination should occur when a close action
  241. '  occurs in the main window.
  242.  
  243. END FUNCTION
  244.  
  245. SUB ChangeButtonFocus.
  246.  
  247. 'Purpose:
  248. '--------
  249. '  Change the visual appearance of a given button or check box.
  250. '  Either display its text in reverse video (background/foreground) to show
  251. '  it has focus, or display its text in normal video (foreground/background).
  252.  
  253. '  This routine only changes the physical appearance of the button/check box,
  254. '  it does NOT give it focus logically (see notes below).
  255.  
  256. '  Typical use would be to give a specific button/check box focus
  257. '  when a window is first created. In this way, the object could
  258. '  serve as the "default" choice (i.e., user could select the
  259. '  default by clicking it with the mouse, or by just hitting ENTER
  260. '  since the default would already have focus).
  261.  
  262. '  Assumes that window containing the button/check box has focus.
  263. '  If it does not, call NewFocusWindow first to give focus to appropriate
  264. '  window.
  265.  
  266. '
  267.  
  268. 'Routine Type:
  269. '-------------
  270. '  Subroutine
  271.  
  272.  
  273. 'Parameters:
  274. '-----------
  275. '      Handle:   handle of button or check box
  276. '      Switch:   0 = give focus (reverse video)
  277. '                1 = clear focus (normal video)
  278.  
  279.  
  280. 'Notes:
  281. '------
  282. '   This routine only changes the visual appearance of the object.
  283. '   To change the logical appearance (i.e., so that other LangWin
  284. '   routines will recognize whether or not the object has focus),
  285. '   you must update the appropriate data structure. In this case,
  286. '   WinParms(CurWinPtr, 16) must be set.
  287.  
  288. '   When giving an object focus (i.e., Switch=0), then the object's
  289. '   handle must be placed into the data structure as follows:
  290. '             WinParms(CurWinPtr,16)=han      ' give object logical focus
  291. '             CALL ChangeButtonFocus(han, 0)  ' give object physical focus
  292.  
  293. '  When clearing focus (i.e., Switch=1), then the data structure must
  294. '  be set to show that no object has focus:
  295. '             WinParms(CurWinPtr,16)=-1       ' clear logical focus
  296. '             CALL ChangeButtonFocus(han, 1)  ' clear physical focus
  297. '
  298.  
  299. END SUB
  300.  
  301. FUNCTION ChangeDir.
  302.  
  303. 'Purpose:
  304. '--------
  305. '   Causes the directory specified in the calling parameter to
  306. '   become the default for the drive specified. Does NOT change the default
  307. '   drive (see ChangeDrive). If calling parameter has no drive spec, then
  308. '   the default drive is assumed.
  309. '
  310. '   (New with V2.0)
  311.  
  312.  
  313. 'Routine Type:
  314. '-------------
  315. '  Function.
  316. '
  317. '
  318. 'Parameters:
  319. '-----------
  320. '   PathName$ - defines the drive (optional) and directory to become current.
  321. '               If drive included, then the default directory for that
  322. '               drive is set to the directory specified.
  323. '               If the drive is omitted, then the default drive is assumed,
  324. '               and the default directory for that drive is set.
  325. '               Either upper or lower case is acceptable.
  326. '               Examples -  a:\my\programs   (drive a:'s dir is changed)
  327. '                           B:test           (drive b:'s dir is changed)
  328. '                           \some\stuff      (default drive's dir is changed)
  329. '
  330.  
  331.  
  332. 'Return Values:
  333. '--------------
  334. '    0:         Change directory was successful.
  335. '   -1:         PathName$ parameter was invalid.
  336. '               Could be caused by an invalid drive letter,
  337. '               or invalid directory specification.
  338. '   -2:         Some other error occurred.
  339. '               OutRegs.ax contains the DOS extended error code.
  340. '
  341. 'Notes:
  342. '------
  343. '  This function calls DOS interrupt 21h, function 3Bh.
  344. '
  345. '  Also see: ChangeDrive, GetCurDir$, GetCurDrive$
  346. '
  347.  
  348. '  ChangeDir will change the defualt directory on the drive specified.
  349. '  The default drive is NOT changed (see ChangeDrive). For example,
  350. '  if C: is the default drive and ChangeDir("a:\mydir") is executed,
  351. '  then the default directory on drive A: becomes \mydir, BUT the default
  352. '  drive still remains C:.
  353.  
  354. '  If the specified drive is not ready, your program will get the
  355. '  standard "not ready" error condition. You can use an ON ERROR routine
  356. '  to trap this condition. The user can be given two alternatives: either
  357. '  RETRY (use a RESUME) or IGNORE (use a RESUME NEXT).
  358.  
  359. END FUNCTION
  360.  
  361. FUNCTION ChangeDrive.
  362.  
  363. 'Purpose:
  364. '--------
  365. '  Change the default drive.
  366. '
  367. '  (New with V2.0)
  368. '
  369.  
  370.  
  371. 'Routine Type:
  372. '-------------
  373. '  Function.
  374. '
  375. '
  376. 'Parameters:
  377. '-----------
  378. '    DriveLetter$   -    Letter to become new default drive.
  379. '                        Can be either upper or lower case.
  380. '                        Only the first character in DriveLetter$ string
  381. '                        will be examined. Cannot be a null string.
  382. '
  383. '
  384. 'Return Values:
  385. '--------------
  386. '     >0:       The number of logical drives specified by the LASTDRIVE
  387. '               parameter in CONFIG.SYS. However, if fewer than 5 drives
  388. '               is specified in LASTDRIVE, then the value of 5 is returned
  389. '               (sorry, this is a DOS quirk, not mine).
  390. '     -1:       Could not change to the specified drive (drive letter
  391. '               specified was probably not a valid drive).
  392. '     -2:       DriveLetter$ was not a letter.
  393. '
  394. 'Notes:
  395. '------
  396. '  This function calls DOS interrupt 21h, function 0Eh.
  397. '
  398. '  Also see: ChangeDir, GetCurDir$, GetCurDrive$
  399. '
  400.  
  401. '  ChangeDrive will not actually cause I/O to the specified drive.
  402. '  Thus, it does not care if the specified drive is ready.
  403. '  You can use ChangeDrive to determine the actual drives
  404. '  configured on a system. Just loop through every possible
  405. '  letter, and issue a ChangeDrive command for it. If return code
  406. '  is 0, then drive letter exists (but you don't know if it's ready).
  407.  
  408.  
  409. END FUNCTION
  410.  
  411. FUNCTION CloseWindow.
  412.  
  413. 'Purpose:
  414. '--------
  415. '  Close/erase the current window.
  416. '  If you want to close a window that is not current,
  417. '  call NewFocusWindow to first bring it into focus.
  418. '
  419. 'Routine Type:
  420. '-------------
  421. '  Function.
  422. '
  423. '
  424. 'Parameters:
  425. '-----------
  426. '  None (the current window is automatically closed).
  427. '
  428. '
  429. 'Return Values:
  430. '--------------
  431. '  0:  window closed successfully
  432. '  1:  there were no windows currently open when this routine was called
  433.  
  434.  
  435. 'Notes:
  436. '-------
  437. '  When the last window is closed, the global variable AnyWinOpen
  438. '  will be set to FALSE.
  439. '  This variable can be used to control a DO/LOOP that executes WinEvent
  440. '  as long as there is an open event on the screen. However, if a Mode 4
  441. '  window is open, then you must use another criteria to
  442. '  end the DO/LOOP because the info only window will always be open.
  443. '  In this case, termination should occur when a close action
  444. '  occurs in the main window.
  445.  
  446. '  Since CloseWindow only operates on the current window, if you want to
  447. '  close a specific window, and are not sure it's current, use the following
  448. '  technique (assume the variable win1 contains the number of the window
  449. '  to be closed):
  450. '           IF IsWinOpen(win1, han) THEN  ' if win1 is open, get its handle
  451. '               zz = CurWinPtr  ' save handle of current window
  452. '               CALL NewFocusWindow(han)  ' make win1 current
  453. '               xx = CloseWindow          ' close it
  454. '               CALL NewFocusWindow(zz)   ' make original win current again
  455. '           END IF
  456.  
  457.  
  458. ' There's another "short-cut" you can use if you just want to close ALL open
  459. ' windows (if you want to close a sub-set of all possible windows,
  460. ' use the above technique with the numbers of each window to be closed).
  461. ' To easily close ALL open windows:
  462.  
  463. '           FOR i = LastWinStack TO 1 STEP -1
  464. '               CALL NewFocusWindow(WinStack(i))
  465. '               x = CloseWindow
  466. '           NEXT
  467.  
  468. ' The WinStack array contains the handles of all open windows, in the order
  469. ' in which they appear on the screen. LastWinStack is a global variable
  470. ' pointing to the current slot. Thus WinStack(1) contains the handle of the
  471. ' first window opened, and WinStack(LastWinStack) contains the handle of the
  472. ' window with focus. The above code just closes each window, from the most
  473. ' current to the least current.
  474.  
  475.  
  476. END FUNCTION
  477.  
  478. FUNCTION DeactivateButton.
  479.  
  480. 'Purpose:
  481. '--------
  482. '   Deactivate a button by setting its text to null (equivalent to
  483. '   "fading" the button's text seen in other GUIs). Once the button is
  484. '   cleared, user can no longer click on it (WinEvent will not recognize
  485. '   the click). This can be used to prevent a user from re-clicking
  486. '   a button until the button's corresponding activity has been completed
  487. '   and your program has re-activated it (see ActivateButton function).
  488.  
  489. '   Window containing the button will be given focus before the
  490. '   button's text is cleared. User has option whether or not
  491. '   to return focus to the window that was current when DeactivateButton
  492. '   was called.
  493.  
  494. '   (New with V2.0)
  495.  
  496.  
  497.  
  498. 'Routine Type:
  499. '-------------
  500. '  Function.
  501.  
  502.  
  503.  
  504. 'Parameters:
  505. '-----------
  506. '  ButtonHandle   - handle of button to be activated
  507.  
  508. '  FocusSw        - switch to determine if window that was current when
  509. '                   DeactivateButton was called should be given focus back
  510. '                   after button has been cleared. DeactivateButton WILL
  511. '                   give focus to the window containing the button before
  512. '                   it clears the text. This could produce one change in
  513. '                   focus (depending on which window had focus when function
  514. '                   was called). After the button has been cleared, you can
  515. '                   either leave focus in the window containing the button,
  516. '                   or give focus back to the original window (may produce
  517. '                   another focus change on screen). See Notes below for
  518. '                   more details on using this parameter.
  519.  
  520. '                   = 0    do not change focus back to original
  521. '                   = 1    change focus back to original window
  522.  
  523.  
  524.  
  525.  
  526. '
  527. 'Return Values:
  528. '--------------
  529. ' 0   - button successfully cleared.
  530. ' 1   - ButtonHandle was not within index range
  531. '       of ButtonsData array. Typically, ButtonHandle
  532. '       should be between 1 and MaxButtons.
  533. ' 2   - ButtonHandle was within range, but it did
  534. '       not have a corresponding open window. This
  535. '       probably means ButtonHandle was incorrect.
  536. ' 3   - ButtonHandle did not correspond to a push
  537. '       button.
  538.  
  539.  
  540. 'Notes:
  541. '------
  542. '   Some comments on the use of the FocusSw parameter:
  543. '   Typically, DeactivateButton is called after a button is clicked to
  544. '   clear the button's text. Once the text is cleared, WinEvent will no
  545. '   longer recognize clicks on the button and it will be deactivated.
  546. '   If DeactivateButton is called immediately after detecting the button
  547. '   click action (3) returned by WinEvent, and before any other window
  548. '   is open, then value of FocusSw does not matter (since window that
  549. '   had focus before the button was deactivated is the same as the window
  550. '   containing the button). In this case, regardless of which value
  551. '   (0 or 1) you assign to the FocusSw parameter, focus will remain in the
  552. '   window containing the button just cleared. You can then go open a child
  553. '   window (or whatever) based upon the meaning of the button clicked.
  554.  
  555. '   Alternatively, you could detect the button click, open a child window
  556. '   (which would have focus after it's opened), call DeactivateButton to
  557. '   go back and clear the button, and set FocusSw=1 in the call to
  558. '   DeactivateButton to cause focus to be given back to the child.
  559. '   This will produce two focus changes (from newly opened child back
  560. '   to parent to clear the button, then from parent back to child).
  561. '   If windows overlap, this will be visually disturbing; I'm not sure
  562. '   why anyone would want to use this alternative. In any case, I've provided
  563. '   the FocusSw just in case you need it.
  564.  
  565.  
  566. END FUNCTION
  567.  
  568. SUB GetButtonPress.
  569.  
  570. 'Purpose:
  571. '--------
  572. '  Returns the current status (up/down) of ALL mouse buttons.
  573. '  For the button specified by input parameter, this routine also
  574. '  returns the number of presses and position of the mouse at the last
  575. '  press (in pixel coordinates). Number of presses is maintained by the
  576. '  mouse driver. It is reset by calling GetButtonPress. Other routines
  577. '  will also cause the count to be reset (see Notes below).
  578. '
  579. '
  580. 'Routine Type:
  581. '-------------
  582. '  Subroutine.
  583. '
  584. '
  585. 'Parameters:
  586. '-----------
  587. '  Button%: on INPUT, specifies the button to be checked
  588. '           [0 = left, 1 = right, 2 = center]
  589. '         : on OUTPUT, specifies CURRENT status of ALL mouse buttons
  590. '           [bits set as follows (shown left to right, bits 2 to 0)]:
  591. '
  592. '                   ..0   left button up
  593. '                   ..1   left button down
  594. '                   .0.   right button up
  595. '                   .1.   right button down
  596. '                   0..   center button (if present) up
  597. '                   1..   center button (if present) down
  598. '
  599. '  Count%:  number of times the button specified by input parameter
  600. '           (Button) was pressed since the last time the count was
  601. '           reset (by a previous call to this routine or others that
  602. '           reset the count - see Notes below).
  603. '
  604. '  Horiz%:  horizontal pixel coordinate of mouse when button specified
  605. '           by input parameter (Button) was last pressed.
  606. '
  607. '  Vert%:   vertical pixel coordinate of mouse when button specified
  608. '           by input parameter (Button) was last pressed.
  609. '
  610. '
  611. 'Notes:
  612. '------
  613. '  This subroutine calls BIOS interrupt 33h, function 05h.
  614. '
  615. '  The input parameter: Button will be MODIFIED by this
  616. '  routine. On input, Button specifies the button to checked for
  617. '  position and press count. On output, Button specifies the
  618. '  up/down status of ALL buttons. Your program must NOT assume that
  619. '  the input parameter (Button) remains unchanged.
  620. '
  621. '  Horizontal/vertical coordinates returned are in PIXELS. If screen
  622. '  positions are desired, use integer division by width/depth of a
  623. '  screen character in pixels to get column/row.
  624. '
  625. '  Calling ShowMouseCursor and HideMouseCursor will also reset
  626. '  the count of button presses (maintained by the mouse driver).
  627. '  So, calling the "show" or "hide" routines while waiting for
  628. '  button press information can result in an inaccurate count
  629. '  (anyway, there should be no need to "hide" the mouse if you are
  630. '  counting the button presses).
  631. '
  632. '  The difference between GetButtonPress and GetMousePos is that
  633. '  GetButtonPress returns the coordinates for the mouse button specified
  634. '  by the input parameter (Button), at the point in time when that button
  635. '  was last pressed (count of presses is also returned).
  636. '  GetMousePos returns the CURRENT coordinates of the mouse, at the point
  637. '  in time when GetMousePos is called (regardless of whether or not any
  638. '  button was ever pressed).
  639. '  GetMousePos is used to "poll" the mouse in real-time to obtain its
  640. '  CURRENT position.
  641. '  GetButtonPress is used to get the mouse's position corresponding to
  642. '  the last time a specific button was pressed (and how many times it
  643. '  was pressed - useful for determining if a double click occurred).
  644. '  Both routines return CURRENT status (up/down) of all buttons.
  645.  
  646. END SUB
  647.  
  648. FUNCTION GetCurDir.$
  649.  
  650. 'Purpose:
  651. '--------
  652. '   Determine the default directory on a specified drive.
  653. '
  654. '   (New with V2.0)
  655. '
  656.  
  657.  
  658. 'Routine Type:
  659. '-------------
  660. '  Function.
  661. '
  662. '
  663. 'Parameters:
  664. '-----------
  665. '  DriveLetter$      -  Letter of the drive to be checked.
  666. '                       If null, then default drive is assumed.
  667. '                       DriveLetter$ can be either upper or lower case.
  668. '                       If DriveLetter$ is non-null, then only the first
  669. '                       character in the string will be examined.
  670.  
  671. '
  672. 'Return Values:
  673. '--------------
  674. '  If successful, string with:   Fully qualified directory name.
  675.  
  676. '  If unsuccessful, STRING with:
  677. '                      "-1"  -  DriveLetter$ did not contain a letter.
  678. '                      "-2"  -  Drive letter was invalid (not on the system).
  679. '                      "-3"  -  Other error (DOS extended error code will
  680. '                               be in OutRegs.ax).
  681. '
  682. 'Notes:
  683. '------
  684. '  This function calls DOS interrupt 21h, function 47h.
  685. '
  686. '  Also see: ChangeDir, ChangeDrive, GetCurDrive$
  687. '
  688. '  To determine success, test first character of returned string.
  689. '  If it was a "\", then function was successful, and returned string
  690. '  contains the fully qualified current directory on specified drive,
  691. '  If first character was a "-", then an error occurred; check rest of string
  692. '  to determine which error.
  693.  
  694. '  If the specified drive is not ready, your program will get the
  695. '  standard "not ready" error condition. You can use an ON ERROR routine
  696. '  to trap this condition. The user can be given two alternatives: either
  697. '  RETRY (use a RESUME) or IGNORE (use a RESUME NEXT).
  698.  
  699. END FUNCTION
  700.  
  701. FUNCTION GetCurDrive.$
  702.  
  703. 'Purpose:
  704. '--------
  705. '  Determine the current drive's letter.
  706. '
  707. '  (New with V2.0)
  708. '
  709.  
  710.  
  711. 'Routine Type:
  712. '-------------
  713. '  Function.
  714. '
  715. '
  716. 'Parameters:
  717. '-----------
  718. '  None.
  719.  
  720.  
  721.  
  722. 'Return Values:
  723. '--------------
  724. '    If successful, then string with:   The current drive's letter.
  725. '                                       The trailing colon (:) is NOT
  726. '                                       included (length of string is 1).
  727. '
  728. '    If unsuccessful, then string with:
  729. '                                 "-1"  DOS returned an invalid letter.
  730. '            
  731. '
  732. 'Notes:
  733. '------
  734. '  This function calls DOS interrupt 21h, function 19h.
  735. '
  736. '  GetCurDrive does not actually do I/O to the drive (the current drive
  737. '  letter is obtained from an internal DOS data structure). Thus, the
  738. '  drive need not be ready when this function is used (any you can not assume
  739. '  that the drive is ready after this function has been used).
  740.  
  741. '  Also see: ChangeDir, ChangeDrive, GetCurDir$
  742. '
  743.  
  744.  
  745. END FUNCTION
  746.  
  747. FUNCTION GetFileNames.
  748.  
  749. 'Purpose:
  750. '--------
  751. '  To extraxct file names or sub-dir names from the current or specified dir,
  752. '  and place them into the passed string array.
  753.  
  754. '  (New with V2.0)
  755. '  (Modified V2.3)
  756. '  - Text$ array is dynamically REDIMed to the correct size
  757. '  - TypeSrch=3 option added
  758.  
  759. 'Routine Type:
  760. '-------------
  761. '  Function.
  762. '
  763. '
  764. 'Parameters:
  765. '-----------
  766. '  TypeSrch:   type of search:
  767. '              = 1: directory names extracted that match filespec$
  768. '                   (read-only, hidden, or system dir names NOT extracted)
  769. '              = 2: file names extracted that match filespec$
  770. '                   (read-only, hidden, or system file names NOT extracted)
  771. '              = 3: ALL names that match filespec$ extracted.
  772. '                   The first byte of the name is prefixed with
  773. '                   a string whose decimal value corresponds to the
  774. '                   file/dir's attribute. See Notes for examples.
  775.  
  776. '  filespec$:  specification for dir or file name (wildcards allowed).
  777. '              examples: "*.*", "*.bas"; "sample??.*" "c:\mylib\*.exe"
  778.  
  779. '  Text$:      String array to hold all file/dir entries matching filespec$.
  780. '              This array MUST be DYNAMIC. It will be REDIMed to the
  781. '              exact size to hold all names extracted, hence it can of
  782. '              any size when this function is called. LBOUND will be 1.
  783. '              UBOUND will be the number of files/dirs extracted.
  784. '              ORIGINAL CONTENTS OF Text$ ARRAY WILL BE DISTROYED.
  785. '              If TypeSrch=3, then LEFT$(Text$(i),1) will be set to the
  786. '              dir/file's attribute and the remaining characters will be
  787. '              the actual name. You'll have to test the attribute byte
  788. '              to determine what type of file/dir it is (and remove
  789. '              the attribute byte from the name before displaying it).
  790. '              See Notes for examples.
  791. '
  792. 'Return Values:
  793. '--------------
  794. '        >0 ==> normal exit - number of names extracted
  795. '        -1 ==> invalid value for TypeSrch (must be 1 or 2)
  796. '        -2 ==> no files/dirs matched filespec$
  797. '        -3 ==> NOT USED
  798. '        -4 ==> NOT USED
  799. '        -5 ==> path not found (filespec$ could be invalid)
  800. '        -6 ==> other error (OutRegs.ax has DOS extended error code)
  801. '
  802. '
  803. '
  804. '
  805. 'Notes:
  806. '------
  807. '  This function calls DOS interrupts 21h, function 4Eh, 4Fh, and 1Ah.
  808.  
  809. '  GetFileNames can be used to extract file and/or dir names from the
  810. '  current dir (for subsequent display in a scrollable text window).
  811. '
  812. '  The string array passed to this function (Text$) will hold all
  813. '  names extracted. It will be REDIMed to the correct size. It MUST
  814. '  be DYNAMIC in the calling program. NOTE: THE ORIGINAL CONTENTS OF THE
  815. '  STRING (Text$) ARRAY WILL BE DISTROYED.
  816.  
  817. '  If the Text$ array is not DYNAMIC, you'll get a "duplicate definition"
  818. '  error when you compile or run a program in the QB environment
  819. '  that calls the GetFileNames function.
  820.  
  821. '  An array can be made DYNAMIC by inclucing a variable name in its
  822. '  original DIM statement
  823. '  (for example: DIM Text$ (1 to x)    where x has been previously defined).
  824. '  Alternatively, you can make ALL arrays dynamic by including the
  825. '  meta-command   '$DYNAMIC at the beginning of your main module.
  826. '
  827.  
  828. '  If this function returns a value > 0, then Text$ contains the files
  829. '  or dirs (depending upon value of TypeSrch) that matched filespec$.
  830. '  Note that if you ask for all dirs (*.*), then two dir names you'll always
  831. '  get (except when in the root directory) are "." and ".." (i.e., the
  832. '  shorthand symbols for the current and parent directory).
  833. '  You can sort the Text$ array, and use RefrestScrollText to place
  834. '  new list into the current window.
  835. '
  836. '  To save string space, you can REDIM the Text$ array
  837. '  as 1 TO 1 prior to calling GetFileNames. GetFileNames will expand this
  838. '  array as necessary to hold all names that match the search criteria.
  839. '  After returning from GetFileNames, ERASE the Text$ array as soon as
  840. '  you are finished with it to save space.
  841.  
  842. '  Example:
  843. '              '$DYNAMIC            ' make all arrays dynamic
  844. '              REDIM Text$(1 TO 1)  ' minimum size to save space
  845. '               .
  846. '               .
  847. '              rc=GetFileNames(2,"*.*",Text$())  ' get all file names
  848. '              IF rc < 0 THEN   ' test for errors
  849. '               .
  850. '              END IF
  851. '               .
  852. '               .
  853. '              FOR i = 1 to rc    ' rc contains number of files in array
  854. '                 PRINT Text$(i)  ' print file names
  855. '              NEXT
  856. '               .
  857. '              ERASE Text$   ' clear the array to save space
  858.  
  859.  
  860. ' Use TypeSrch=3 if you want to get ALL names in the current or specified
  861. ' directory that match filespec$. In this case, each name is prefixed with
  862. ' a one-byte string whose decimal value is the file/dir's attribute.
  863. ' Attribute bits can take the following values:
  864.  
  865. '         BITS        DECIMAL        MEANING
  866. '       .... ...1        1           Read Only
  867. '       .... ..1.        2           Hidden
  868. '       .... .1..        4           System
  869. '       .... 1...        8           Volume Label
  870. '       ...1 ....       16           Sub-Directory
  871. '       ..1. ....       32           Archive
  872. '       .1.. ....        x           UNUSED
  873. '       1... ....        x           UNUSED
  874.  
  875. ' Attribute bits can occur in combinations. For example, a file that is
  876. ' marked as Read Only and Hidden will have a decimal attribute byte of 3.
  877. ' "Regular" files will usually have a decimal attribute byte of 0 or 32.
  878. ' "Regular" directories will usually have a decimal attribute byte of 16.
  879.  
  880. ' When TypeSrch=3 is used, you must test the first byte of each file name
  881. ' to determine its type, then remove the first byte if you are going to
  882. ' display the names:
  883.  
  884. '      REDIM Text$(1 to 1)
  885. '      rc=GetFileNames(3,"*.bas",Text$)  ' get all names that match *.bas
  886. '      IF rc < 0 THEN
  887. '        process the error
  888. '        END
  889. '      END IF
  890.  
  891. '      test the attributes
  892. '      FOR i = 1 TO rc
  893. '         att=ASC(LEFT$(Text$(i),1))       ' get attribute byte
  894. '         IF att = zz THEN ....            ' process the attribute byte
  895. '         x=LEN(Text$(i)                   ' get length
  896. '         Text$(i)=RIGHT$(Text$(i),x-1)    ' strip attribute byte
  897. '      NEXT
  898.  
  899. '      z=OpenScrollWindow( ........., Text$, .........)  ' open scroll window
  900. '      ERASE Text$                         ' save some string space
  901.  
  902. END FUNCTION
  903.  
  904. SUB GetMousePos.
  905.  
  906. 'Purpose:
  907. '--------
  908. '  Returns the current status (up/down) of all mouse buttons
  909. '  and current position (in pixel coordinates).
  910. '
  911. '
  912. 'Routine Type:
  913. '-------------
  914. '  Subroutine.
  915. '
  916. '
  917. 'Parameters:
  918. '-----------
  919. '  Button%: the CURRENT status of all mouse buttons.
  920. '           [bits set as follows (shown left to right, bits 2 to 0)]:
  921. '
  922. '                   ..0   left button up
  923. '                   ..1   left button down
  924. '                   .0.   right button up
  925. '                   .1.   right button down
  926. '                   0..   center button (if present) up
  927. '                   1..   center button (if present) down
  928. '
  929. '  Horiz%:  current horizontal pixel coordinate of mouse.
  930. '  Vert%:   current vertical pixel coordinate of mouse.
  931. '
  932. '
  933. 'Notes:
  934. '------
  935. '  This subroutine calls BIOS interrupt 33h, function 03h.
  936. '
  937. '  Horizontal/vertical coordinates returned are in PIXELS. If screen
  938. '  positions are desired, use integer division by width/depth of
  939. '  character in pixels to get column/row.
  940. '
  941. '  The difference between GetButtonPress and GetMousePos is that
  942. '  GetButtonPress returns the coordinates for the mouse button specified
  943. '  by the input parameter (Button), at the point in time when that button
  944. '  was last pressed (count of presses is also returned).
  945. '  GetMousePos returns the CURRENT coordinates of the mouse, at the point
  946. '  in time when GetMousePos is called (regardless of whether or not any
  947. '  button was ever pressed).
  948. '  GetMousePos is used to "poll" the mouse in real-time to obtain its
  949. '  CURRENT position.
  950. '  GetButtonPress is used to get the mouse's position corresponding to
  951. '  the last time a specific button was pressed (and how many times it
  952. '  was pressed - useful for determining if a double click occurred).
  953. '  Both routines return CURRENT status (up/down) of all buttons.
  954.  
  955. END SUB
  956.  
  957. FUNCTION GetVerNum.$
  958.  
  959. 'Purpose:
  960. '--------
  961. '  Returns version number of LangWin.
  962. '  [CTRL-A from any window will also display version number]
  963. '
  964. '
  965. 'Routine Type:
  966. '-------------
  967. '  Function.
  968. '
  969. '
  970. 'Parameters:
  971. '-----------
  972. '  None.
  973. '
  974. '
  975. 'Return Values:
  976. '--------------
  977. '  String with version number.
  978.  
  979.  
  980. END FUNCTION
  981.  
  982. FUNCTION GrowScrollText.
  983.  
  984. 'Purpose:
  985. '--------
  986. '   This function allows you to dynamically add entries to the list of
  987. '   scrollable text in the CURRENT window. The text is appended to the
  988. '   end of the CURRENT window's scrollable text array, and the array
  989. '   is re-displayed in the CURRENT window.
  990. '   (New with V2.3)
  991.  
  992.  
  993. 'Routine Type:
  994. '-------------
  995. '  Function.
  996.  
  997.  
  998. 'Parameters:
  999. '-----------
  1000. '  Text$   -  text string to be added to end of CURRENT window's
  1001. '             scrollable text array and displayed in the CURRENT
  1002. '             window's scrollable text area.
  1003.  
  1004.  
  1005. '
  1006. 'Return Values:
  1007. '--------------
  1008. '   0  - success
  1009. '  -1  - current window is not a scrollable text window (i.e., it was
  1010. '        not opened via OpenScrollText).
  1011. '  -2  - no more room in scrollable text array for another entry.
  1012. '        there's already MaxTextLines lines of text in the array.
  1013. '        you'll either have to increase MaxTextLines, or handle
  1014. '        the case where you allow the user to browse the list
  1015. '        as it exists, then click a button to close the window, re-open it
  1016. '        with null text, and continue filling the window's text area.
  1017.  
  1018.  
  1019.  
  1020. 'Notes:
  1021. '------
  1022.  
  1023. ' If the list of scrollable text in the current window does not fill the
  1024. ' text area defined when the window was opened, then the text string passed
  1025. ' to GrowScrollText will be be displayed at the bottom of the visible list.
  1026. ' If the list of scrollable text fills the text area, then text is scrolled
  1027. ' up and the new string passed to GrowScrollText is displayed at the bottom
  1028. ' of the text area. Note that the list of scrollable text could be null, in
  1029. ' which case the first call to GrowScrollText will create the first line of
  1030. ' scrollable text in the current window (but a scrollable text window must
  1031. ' have been opened, otherwise GrowScrollText will not work properly).
  1032.  
  1033. ' GrowScrollText will operate on the current window with focus. If that
  1034. ' window is not a scrollable text window, no action is taken and an error
  1035. ' code (-1) is returned (i.e., even if the scrollable text array is null,
  1036. ' the window MUST have been opened with OpenScrollText and NOT with
  1037. ' BlankWin). If the scrollable text array for the current window is already
  1038. ' full (i.e., it has MaxTextLines lines of text already defined), no action
  1039. ' is taken and an error code (-2) is returned.
  1040.  
  1041. ' GrowScrollText can be used to give the user visual feedback as a long
  1042. ' running task progresses. Suppose you have a routine that searches for
  1043. ' specific records in a data base, and you want to display these in a
  1044. ' scrollable list for your user to browse. GrowScrollText can be used to
  1045. ' show the records being dynamically added to the list as they are found.
  1046. ' The following pseudo code will implement this example:
  1047.  
  1048.  
  1049. '  DIM Text(1 to 1) AS STRING  ' scrollable text, init as null
  1050. '  Above array need only have 1 entry (initially null). It's only used by
  1051. '  OpenScrollText to initialize LangWin's data structure SaveText.
  1052. '  Thereafter, GrowScrollText will actually "grow" the text in SaveText.
  1053. '           .
  1054. '           .
  1055. '  w1=OpenScrollWindow( ..... ,Text(), .....) scrollable win with null text
  1056. '  ' put some buttons in the window
  1057. '           .
  1058. '           .
  1059. '  DO WHILE AnyWinOpen         ' process windows
  1060. '       wn=WinEvent(action)       ' wait for an action
  1061. '       ' process actions in windows
  1062. '            .
  1063. '            .
  1064. '            .
  1065. '
  1066. '       ' assume that at this point you determine the need to search a
  1067. '       ' database for records, and to display the results in a scrollable
  1068. '       ' window (w1) where the user can browse the results.
  1069. '
  1070. '       ' w1 is the number of the open window that will contain the
  1071. '       ' scrollable text. at this point, the scrollable text array is null.
  1072. '       x=IsWinOpen(w1,Han)     ' get handle of w1 and save in Han
  1073. '
  1074. '       ' search loop
  1075. '       DO
  1076. '           ' first, you must make sure window with text (w1) is current
  1077. '           CALL NewFocusWindow(Han)   ' give focus to text window
  1078. '   
  1079. '           rec$=GetNextMatch$(parms)  ' get a record
  1080. '           IF rec$="" THEN EXIT DO    ' see if search is done
  1081. '           ' note: GetNextMatch$ is NOT part of LangWin. it's
  1082. '           ' a fictitious function used to illustrate a routine
  1083. '           ' that you might call to get a record and return in text string.
  1084. '           ' i assume a null value is returned when search is completed.
  1085. '
  1086. '           rc=GrowScrollText(rec$)     ' display rec in window
  1087. '           SELECT CASE rc  ' test above return code
  1088. '           CASE -1   ' current window is not a scrollable text window
  1089. '               ' process the error
  1090. '           CASE -2   ' scrollable text array is full
  1091. '              ' process the error. this might include allowing
  1092. '              ' the user to browse the scrollable text and waiting
  1093. '              ' for a CONTINUE button to be clicked. when this
  1094. '              ' button is clicked, you could close the window,
  1095. '              ' re-open it (to clear text), and continue the search.
  1096. '           END SELECT
  1097. '
  1098. '           ' using the time-out techniques from Section 6.22, you could
  1099. '           ' also include a STOP button to interrupt the search.
  1100. '           ' assume handle of STOP button is: Stop1
  1101. '           aa=-999          ' set time out option
  1102. '           x=WinEvent(aa)   ' wait for 0.5 sec for an event
  1103. '       ' loop until STOP button is clicked
  1104. '       LOOP UNTIL (aa=3 AND WinParms(CurWinPtr,16)=Stop1)
  1105. '
  1106.  
  1107. END FUNCTION
  1108.  
  1109. SUB HideMouseCursor.
  1110.  
  1111. 'Purpose:
  1112. '--------
  1113. '  Hides mouse cursor before displaying anything on the screen.
  1114. '
  1115. '
  1116. 'Routine Type:
  1117. '-------------
  1118. '  Subroutine.
  1119. '
  1120. '
  1121. 'Parameters:
  1122. '-----------
  1123. '  None.
  1124. '
  1125. '
  1126. 'Notes:
  1127. '------
  1128. '  This subroutine calls BIOS interrupt 33h, function 02h.
  1129. '
  1130. '  The mouse cursor must be hidden before writing anything to the screen.
  1131. '  Otherwise, any character written to the same position as the mouse
  1132. '  cursor will not be displayed. See ShowMouseCursor for inverse function.
  1133. '
  1134. '  LangWin sets a global flag (HaveMouse) to true if mouse exists.
  1135. '  This flag should be tested before calling HideMouseCursor:
  1136. '        IF HaveMouse THEN CALL HideMouseCursor
  1137. '
  1138. '  Also see: ShowMouseCursor, MouseExists, and InitMouse.
  1139.  
  1140. END SUB
  1141.  
  1142. FUNCTION InitMouse.
  1143.  
  1144. 'Purpose:
  1145. '--------
  1146. '  Initialize the mouse.
  1147. '
  1148. '
  1149. 'Routine Type:
  1150. '-------------
  1151. '  Function.
  1152. '
  1153. '
  1154. 'Parameters:
  1155. '-----------
  1156. '  NumButtons:  number of buttons on the mouse
  1157. '
  1158. '
  1159. 'Return Values:
  1160. '--------------
  1161. '  TRUE (-1):  mouse was successfully initialized
  1162. '  FALSE (0):  mouse was not successfully initialized
  1163. '
  1164. '
  1165. 'Notes:
  1166. '------
  1167. '  This function calls BIOS interrupt 33h, function 00h.
  1168. '
  1169. '  Also see: MouseExists.
  1170. '
  1171. '  MouseExists should be called BEFORE InitMouse to insure that
  1172. '  a mouse exists. Otherwise, calling InitMouse without a mouse could
  1173. '  crash the system. InitMouse must be called once to initialize the
  1174. '  mouse before performing any other mouse functions.
  1175.  
  1176. END FUNCTION
  1177.  
  1178. FUNCTION IsWinOpen.
  1179.  
  1180. 'Purpose:
  1181. '--------
  1182. '  Given a window number, determine if it is open (TRUE) or closed (FALSE).
  1183. '  If open, determine the window's handle.
  1184. '  (New with V2.0)
  1185. '
  1186.  
  1187. 'Routine Type:
  1188. '-------------
  1189. '  Function.
  1190.  
  1191.  
  1192. 'Parameters:
  1193. '-----------
  1194. '    wn%:  -  window's number (input)
  1195. '    wh%   -  window's handle if it's open, else -1 (output)
  1196.  
  1197.  
  1198. 'Return Values:
  1199. '--------------
  1200. '   TRUE  - window was open
  1201. '   FALSE - window was not open
  1202.  
  1203.  
  1204. 'Notes:
  1205. '------
  1206. '   WinNum array is scanned for match on window number.
  1207. '   If match found, index in WinNum is the window's handle.
  1208.  
  1209. '   IsWinOpen can be used to determine if a specific child window
  1210. '   is open before closing the parent.
  1211.  
  1212. '   All info for open windows are stored in data structures indexed
  1213. '   by window's handle. If you know a window's number (returned by the
  1214. '   corresponding "make" routine), then IsWinOpen can be used to determine
  1215. '   if the window is open, and if so, its handle. The handle can be used
  1216. '   as an index into the data structures to examine the window's status.
  1217. '   The handle is also needed if you call NewFocusWindow to bring a new
  1218. '   window into focus.
  1219.  
  1220. END FUNCTION
  1221.  
  1222. SUB LangWinInit.
  1223.  
  1224. 'Purpose:
  1225. '--------
  1226. '  Initialize LangWin's global variables.
  1227. '
  1228. '
  1229. 'Routine Type:
  1230. '-------------
  1231. '  Subroutine.
  1232. '
  1233. '
  1234. 'Parameters:
  1235. '-----------
  1236. '  None.
  1237. '
  1238. '
  1239. 'Notes:
  1240. '------
  1241. '  Must be called once in main module before performing any of LangWin's
  1242. '  routines. LangWinInit will also initialize the mouse if it exists.
  1243.  
  1244. '  if you get a "subscript out of range" error while
  1245. '  in this routine, be sure you called QB with /ah.
  1246. '  then try reducing the value of MaxWindows.
  1247. '  check the WIDTH command; reduce number of columns,
  1248. '  and/or number of rows.
  1249.  
  1250. END SUB
  1251.  
  1252. FUNCTION MakeBox.
  1253.  
  1254. 'Purpose:
  1255. '--------
  1256. '  Draw a box in current window.
  1257. '
  1258. '
  1259. 'Routine Type:
  1260. '-------------
  1261. '  Function.
  1262. '
  1263. '
  1264. 'Parameters:
  1265. '-----------
  1266. '  StartBoxRow%:   starting row (upper left)
  1267. '  StartBoxCol%:   starting column (upper left)
  1268. '  EndBoxRow%:     ending row (bottom right)
  1269. '  EndBoxCol%:     ending column (bottom right)
  1270. '  BoxLinType%:    1 (single line); 2 (double line)
  1271. '  BoxColor%:      color attribute of box (0-15)
  1272. '
  1273. '
  1274. 'Return Values:
  1275. '--------------
  1276. '  0:     box was successfully displayed
  1277. '  1:     invalid box line type parameter (not a 1 or 2)
  1278. '  2:     box would extend beyond current window.
  1279. '
  1280. '
  1281. 'Notes:
  1282. '------
  1283. '  Starting/ending rows and columns are relative to the current window.
  1284. '  Row 0, Column 0, represent the first row/column in the window,
  1285. '  regardless of where the window is located on the screen
  1286. '  (first /last row and columns contain the window's border).
  1287. '  Box will not be drawn if it would extend beyond boundaries of the
  1288. '  current window (or if it would overlay the boundary itself).
  1289.  
  1290. END FUNCTION
  1291.  
  1292. FUNCTION MakeCheckBox.
  1293.  
  1294. 'Purpose:
  1295. '--------
  1296. '  Open/display a check box in the current window.
  1297. '  Handle of check box will be returned.
  1298. '
  1299. '
  1300. 'Routine Type:
  1301. '-------------
  1302. '  Function.
  1303. '
  1304. '
  1305. 'Parameters:
  1306. '-----------
  1307. '  Row%:        row where Check Box will be placed
  1308. '  Col%:        starting column
  1309. '  Foreg%:      foreground color attribute (0-15)
  1310. '  Backg%:      background color attribute (0-15)
  1311. '  Default%:    initial default state of Check Box
  1312. '               [MUST either be CheckOn (box is selected/down),
  1313. '               or CheckOff (box is not selected/up. CheckOn and
  1314. '               CheckOff are global variables initialized by LangWinInit]
  1315. '
  1316. '
  1317. 'Return Values:
  1318. '--------------
  1319. '  >0:  check box successfully created (positive value is handle number)
  1320. '  -1:  check box would extend beyond current window
  1321. '  -3:  length not big enough for default box text
  1322. '       [should not see this error since box text is pre-defined]
  1323. '  -4:  not enough storage for another button
  1324. '       [must increase the value of global parameter MaxButtons]
  1325. '  -5:  foreground color attribute invalid (must be 0-15)
  1326. '  -6:  background color attribute invalid (must be 0-15)
  1327. '  -7:  shadow switch value invalid
  1328. '       [should not see this error since shadow switch is pre-defined]
  1329. '  -8:  default box state not valid
  1330. '       [it MUST be either CheckOn or CheckOff]
  1331. '
  1332. '
  1333. 'Notes:
  1334. '------
  1335. '  MakeCheckBox calls MakePushButton to actually display the Check Box
  1336. '  (since Check Boxes are really just another type of button).
  1337. '
  1338. '  Row and column are relative to the current window.
  1339. '  Row 0, Column 0, represent the first row/column in the window,
  1340. '  regardless of where the window is located on the screen
  1341. '  (first /last row and columns contain the window's border).
  1342. '  Check Box will not be opened if it would extend beyond boundaries
  1343. '  of the current window (or if it would overlay the boundary itself).
  1344. '
  1345. '  The handle value returned must be saved.
  1346. '  After calling WinEvent to wait for an event in the current window,
  1347. '  you must determine which event occurred (see WinEvent for details).
  1348. '  Depending upon the event, you may need to determine the state of
  1349. '  Check Boxes in the window. Use the saved handles of all appropriate
  1350. '  Check Boxes to index the ButtonsData array which contains the status
  1351. '  of all buttons. The 7th entry for each button contains a switch
  1352. '  that describes whether or not it has a shadow (1=yes; 0=no). For
  1353. '  Check Boxes, the shadow determines if it was selected
  1354. '  (1=shadow - box NOT selected; 0=no shadow - box was selected).
  1355. '
  1356. '  If Han represents the handle value of a specific Check Box, the
  1357. '  following code illustrates how to determine if the box was selected:
  1358. '
  1359. '     IF ButtonsData(Han, 7) = 1 THEN ... the Check Box was NOT selected.
  1360. '     IF ButtonsData(Han, 7) = 0 THEN ... the Check Box was selected.
  1361.  
  1362. END FUNCTION
  1363.  
  1364. FUNCTION MakeHorizLine.
  1365.  
  1366. 'Purpose:
  1367. '--------
  1368. '  Draw a horizontal line across current window.
  1369. '
  1370. '
  1371. 'Routine Type:
  1372. '-------------
  1373. '  Function.
  1374. '
  1375. '
  1376. 'Parameters:
  1377. '-----------
  1378. '  Row%:       row where line will be placed
  1379. '  LineType%:  type of line (1=single; 2=double)
  1380. '
  1381. '
  1382. 'Return Values:
  1383. '--------------
  1384. '  0:     success
  1385. '  1:     invalid line type parameter (must be 1 or 2)
  1386. '  2:     line would extend beyond window boundary or
  1387. '         fall on same row as border.
  1388. '
  1389. '
  1390. 'Notes:
  1391. '------
  1392. '  Row where line is placed is relative to the current window.
  1393. '  Row 0 represent the first row in the window,
  1394. '  regardless of where the window is located on the screen
  1395. '  (first /last row contains the window's border).
  1396. '  Line will not be drawn if it would extend beyond boundaries of the
  1397. '  current window (or if it would overlay the top/bottom boundary itself).
  1398.  
  1399. END FUNCTION
  1400.  
  1401. FUNCTION MakeInputField.
  1402.  
  1403. 'Purpose:
  1404. '--------
  1405. '  Open/display an Input Field in the current window
  1406. '  [to be used for data entry/modification]
  1407. '  [can also be used for entering a password - see length field parameter]
  1408. '
  1409. 'Routine Type.
  1410. '-------------
  1411. '  Function.
  1412. '
  1413. '
  1414. 'Parameters:
  1415. '-----------
  1416. '  Row%:        row where input field will be placed
  1417. '  Col%:        starting column
  1418. '  Length%:     length of input field area
  1419. '               (if a negative value is used for length, input field will
  1420. '               be used for password entry - only * will be displayed)
  1421. '  FieldText$:  default text (null if none)
  1422. '  Foreg%:      foreground color attribute (0-15)
  1423. '  Backg%:      background color attribute (0-15)
  1424. '
  1425. '
  1426. 'Return Values:
  1427. '--------------
  1428. '  >0:  field successfully created (positive value is handle number)
  1429. '  -1:  field would extend beyond current window
  1430. '  -4:  not enough storage for another field
  1431. '       [must increase value of global parameter MaxButtons]
  1432. '  -5:  foreground color attribute invalid (0-15)
  1433. '  -6:  background color attribute invalid (0-15)
  1434. '
  1435. '
  1436. 'Notes:
  1437. '------
  1438. '  Row and column are relative to the current window.
  1439. '  Row 0, Column 0, represent the first row/column in the window,
  1440. '  regardless of where the window is located on the screen
  1441. '  (first /last row and column contain the window's border).
  1442. '  Input Field will not be opened if it would extend beyond boundaries
  1443. '  of the current window (or if it would overlay the boundary itself).
  1444. '
  1445. '  The handle value returned must be saved.
  1446. '  After calling WinEvent to wait for an event in the current window,
  1447. '  you must determine which event occurred (see WinEvent for details).
  1448. '  Depending upon the event, you may need to access/modify the contents
  1449. '  of Input Fields in the window. Use the saved handles of all appropriate
  1450. '  Input Fields to index the ButtonsText array which contains the
  1451. '  contents of all fields. You can examine these contents to see their
  1452. '  current values. If the contents contains numeric data, use VAL to
  1453. '  extract the numeric value. Then use STR$ if the contents are to be
  1454. '  updated with new numeric data (the contents of ButtonsText must always
  1455. '  be STRING). Once the contents of ButtonsText have been modified,
  1456. '  use the ReShowInputField subroutine to re-display the new contents
  1457. '  in the current window.
  1458. '
  1459. '  If Han is the handle of an Input Field (returned by MakeInputField),
  1460. '  the following code adds one to the Input Field and re-displays it:
  1461. '
  1462. '        value=VAL(ButtonsText(Han))+1   ' get value and increment by 1
  1463. '        ButtonsText(Han)=STR$(value)    ' update field's contents
  1464. '        CALL ReShowInputField(Han)      ' re-display input field
  1465.  
  1466.  
  1467. '  By using a negative value for length, the input field can be used for
  1468. '  password entry. In this case, regardless of what is entered, only *
  1469. '  will be displayed. The actual text entered (i.e., the password) will
  1470. '  be stored in ButtonsText(Han) - just as for any other input field.
  1471. '  An alternative technique would be to use the same values for
  1472. '  foreground and background colors. In this case, nothing will be visible
  1473. '  when text is entered into the field.
  1474.  
  1475. END FUNCTION
  1476.  
  1477. FUNCTION MakePushButton.
  1478.  
  1479. 'Purpose:
  1480. '--------
  1481. '  Open/display a Push Button in the current window.
  1482. '
  1483. '
  1484. 'Routine Type:
  1485. '-------------
  1486. '  Function.
  1487. '
  1488. '
  1489. 'Parameters:
  1490. '-----------
  1491. '  Row%:        row where button will be placed
  1492. '  Col%:        starting column
  1493. '  Length%:     length of button area
  1494. '  ButtonText$: text contents of button
  1495. '  Foreg%:      foreground color attribute (0-15)
  1496. '  Backg%:      background color attribute (0-15)
  1497. '  Shadow%:     switch: 0=no shadow; 1=shadow
  1498. '
  1499. '
  1500. 'Return Values:
  1501. '--------------
  1502. '  >0:  button successfully created (positive value is handle number)
  1503. '  -1:  button would extend beyond current window
  1504. '  -3:  length not big enough for all of ButtonText$
  1505. '  -4:  not enough storage for another button
  1506. '       [must increase value of global parameter MaxButtons]
  1507. '  -5:  foreground color attribute invalid (must be 0-15)
  1508. '  -6:  background color attribute invalid (must be 0-15)
  1509. '  -7:  shadow switch value invalid (must be 0 or 1)
  1510. '
  1511. '
  1512. 'Notes:
  1513. '------
  1514. '  Row and column are relative to the current window.
  1515. '  Row 0, Column 0, represent the first row/column in the window,
  1516. '  regardless of where the window is located on the screen
  1517. '  (first /last row and column contain the window's border).
  1518. '  Push Button will not be opened if it would extend beyond boundaries
  1519. '  of the current window (on the border is ok - that's how a menu bar
  1520. '  at top of window can be created).
  1521. '
  1522. '  The handle value returned must be saved.
  1523. '  After calling WinEvent to wait for an event in the current window,
  1524. '  you must determine which event occurred (see WinEvent for details).
  1525. '  If the event was a button click, then WinEvent will return a 3, and
  1526. '  you will need to determine exactly which button was selected. Compare
  1527. '  the handle of the button that was clicked to all saved button handles.
  1528. '  The action taken for each particular button handle is user defined
  1529. '  based upon the meaning of the button.
  1530. '
  1531. '  If WinEvent returns a value of 3, then WinParms(CurWinPtr,16)
  1532. '  contains the handle of the push button that caused the click (see
  1533. '  WinEvent for additional details). The following code shows a technique
  1534. '  for determining which button was clicked:
  1535. '
  1536. '        Han=WinParms(CurWinPtr,16) ' handle of button that was clicked
  1537. '        SELECT CASE Han
  1538. '        CASE b1
  1539. '              ' action for button whose saved handle is b1
  1540. '        CASE b2
  1541. '              ' action for button whose saved handle is b2
  1542. '          .
  1543. '          .
  1544. '          .
  1545. '        END SELECT
  1546.  
  1547. END FUNCTION
  1548.  
  1549. FUNCTION MakeVertLine.
  1550.  
  1551. 'Purpose:
  1552. '--------
  1553. '  Draw a vertical line down current window.
  1554. '
  1555. '
  1556. 'Routine Type:
  1557. '-------------
  1558. '  Function.
  1559. '
  1560. '
  1561. 'Parameters:
  1562. '-----------
  1563. '  Col%:       column where line will be placed
  1564. '  LineType%:  type of line (1=single; 2=double)
  1565. '
  1566. '
  1567. 'Return Values:
  1568. '--------------
  1569. '  0:     success
  1570. '  1:     invalid line type parameter (must be 1 or 2)
  1571. '  2:     line would extend beyond window boundary
  1572. '         or fall on same column as border.
  1573. '
  1574. '
  1575. 'Notes:
  1576. '------
  1577. '  Column where line is placed is relative to the current window.
  1578. '  Column 0 represent the first column in the window,
  1579. '  regardless of where the window is located on the screen
  1580. '  (first /last column contains the window's border).
  1581. '  Line will not be drawn if it would extend beyond boundaries of the
  1582. '  current window (or if it would overlay the side boundaries).
  1583.  
  1584. END FUNCTION
  1585.  
  1586. FUNCTION MouseExists.
  1587.  
  1588. 'Purpose:
  1589. '--------
  1590. '  Determines if the mouse driver has been installed.
  1591. '
  1592. '
  1593. 'Routine Type:
  1594. '-------------
  1595. '  Function:
  1596. '
  1597. '
  1598. 'Parameters:
  1599. '-----------
  1600. '  None.
  1601. '
  1602. '
  1603. 'Return Values:
  1604. '--------------
  1605. '  TRUE (-1):  mouse driver has been installed
  1606. '  FALSE (0):  mouse driver was not installed
  1607. '
  1608. '
  1609. 'Notes:
  1610. '------
  1611. '  This routine does NOT install the mouse driver, it only checks
  1612. '  to see if it exists.
  1613. '
  1614. '  It first looks in the interrupt vector table (segment 0) which has
  1615. '  4 bytes for each interrupt routine. The mouse interrupt (33h) vector
  1616. '  begins at decimal 204 (33h=51d; 51d * 4 bytes/entry = 204).
  1617. '
  1618. '  If the 4 bytes at 204-207 are zero, the mouse driver not installed.
  1619. '  Else, the contents of the address specified by the 4 bytes at 204-207
  1620. '  are compared to the value 207 (i.e., an IRET instruction). If there is
  1621. '  a match, mouse driver not installed. Otherwise, mouse driver assumed
  1622. '  to be installed.
  1623. '
  1624. '  This routine is required for computers running DOS V2 or earlier.
  1625. '  They leave the mouse interrupt (&h33) undefined if no mouse exists,
  1626. '  and calling the mouse interrupt would crash the system.
  1627. '
  1628. '  Before using mouse functions, first call MouseExists to
  1629. '  see if the driver has been installed. If it has, then call InitMouse
  1630. '  to initialize the mouse driver. Once the driver has been successfully
  1631. '  initialized, you can call other mouse functions.
  1632.  
  1633. END FUNCTION
  1634.  
  1635. SUB NewFocusWindow.
  1636.  
  1637. 'Purpose:
  1638. '--------
  1639. ' Change the focus to a new window.
  1640.  
  1641. ' (New with V2.0)
  1642.  
  1643.  
  1644. 'Routine Type:
  1645. '-------------
  1646. '  Subroutine.
  1647.  
  1648.  
  1649. 'Parameters:
  1650. '-----------
  1651. '  NewWinHan:   handle of window to be given focus.
  1652. '
  1653. '
  1654. 'Notes:
  1655. '------
  1656. ' On entry, CurWinPtr points to current window's handle.
  1657. ' This window is top one in WinStack (entry with highest index).
  1658.  
  1659. ' On exit, CurWinPtr will be set to NewWinHan.
  1660. ' NewWinHan will be removed from WinStack (wherever it is),
  1661. ' placed on top in WinStack (entry with highest index), and
  1662. ' remaining handles pushed down.
  1663.  
  1664. ' WARNING: if the input parameter (NewWinHan) is not a valid handle
  1665. ' (i.e., NewFocusWindow scans WinStack for the handles of all open windows),
  1666. ' then an error message is displayed (with the invalid handle's value),
  1667. ' and the user's program is terminated. Thus, you should be very careful
  1668. ' when calling NewFocusWindow to insure that you have a valid handle
  1669. ' associated with an open window. See IsWinOpen which can be used to extract
  1670. ' the handle of an open window given its window number.
  1671. '
  1672. ' Typical use of NewFocusWindow:
  1673. ' EXIT button in main window was clicked (so main window has focus).
  1674. ' Main window could have a child open. Before main window is closed,
  1675. ' you need to close the child window (if it's open). Assume window number
  1676. ' of child is saved in variable called ChildNum.
  1677. '           IF IsWinOpen(ChildNum, han) THEN  ' get handle of child
  1678. '               zz = CurWinPtr  ' save handle of main window (it's current)
  1679. '               CALL NewFocusWindow(han)  ' make child win current
  1680. '               xx = CloseWindow          ' close it
  1681. '               CALL NewFocusWindow(zz)   ' make main win current
  1682. '           END IF
  1683. '           xx = CloseWindow          ' close main
  1684.  
  1685.  
  1686. END SUB
  1687.  
  1688. FUNCTION OpenScrollWindow.
  1689.  
  1690. 'Purpose:
  1691. '--------
  1692. '  Open/display window with a scrollable text area.
  1693. '  New window will be given focus.
  1694. '
  1695. '
  1696. 'Routine Type:
  1697. '-------------
  1698. '  Function.
  1699. '
  1700. '
  1701. 'V2.0 Changes:
  1702. '-------------
  1703. '  Negative value for WinColor% will make window unmovable.
  1704. '  New CloseIcon% parameter required.
  1705. '  New ModeSw% parameter required.
  1706. '  Negative value for ModeSw% will make window shadowless.
  1707. '  Return values changed:
  1708. '    Negative value returned if window not opened successfully.
  1709. '    Window's number (>0) returned if window is opened successfully.
  1710. '    0 is not a valid return code.
  1711. '    -11 is a new return code.
  1712. '    -12 is a new return code.
  1713.  
  1714.  
  1715. 'V2.3 Changes:
  1716. '-------------
  1717. ' In previous versions of LangWin, if OpenScrollWindow was called with
  1718. ' UBOUND(Text$) > the global variable MaxTextLines, a run-time error would
  1719. ' immediately terminate your program.
  1720.  
  1721. ' As of V2.3, if UBOUND(Text$) > MaxTextLines,
  1722. ' the scrollable text window will be opened, but only lines 1
  1723. ' through MaxTextLines of the Text$ array will be scrollable. To let you
  1724. ' know that all of the Text$ array is not available in the scroll window,
  1725. ' the MaxTextLine entry will appear as:   (Incomplete List)
  1726. ' The original Text$ array will not be altered; Text$(MaxTextLine) remains
  1727. ' unchanged. The string "(Incomplete List)" only appears in the window's
  1728. ' scrollable list.
  1729.  
  1730.  
  1731. 'Parameters:
  1732. '-----------
  1733. '  StartRow%:     starting row (upper left)
  1734. '  StartCol%:     starting column (upper left)
  1735. '  EndRow%:       ending row (bottom right)
  1736. '  EndCol%:       ending column (bottom right)
  1737. '  WinColor%:     color attribute of window (0-15)
  1738. '                 (NEGATIVE value will make window unmovable)
  1739. '  BorderColor%:  color attribute of border (0-15)
  1740. '                 (NEGATIVE value will prevent window from being resized)
  1741. '  BorderType%:   1=single line; 2=double line
  1742. '                 [if BorderType < 0 (i.e., -1 or -2), then no scroll
  1743. '                 bar or arrows will be displayed (even if text too big for
  1744. '                 win). use this option if you know that the number of lines
  1745. '                 of scrollable text is smaller than the lines available
  1746. '                 in the text window, AND you don't want scroll bar & arrows.
  1747. '                 if BorderType > 0, and number of
  1748. '                 lines of scrollable text is smaller than the window,
  1749. '                 then the scroll bar will automatically be omitted,
  1750. '                 but the scroll arrows will still be displayed.]
  1751. '  TextColor%:    color attribute for scrollable text in the window (0-15)
  1752. '                 (also used for close icon, scroll bar,and slider
  1753. '                 if present)
  1754. '  Text$:         array with text to be scrolled. will be placed into
  1755. '                 a vacant slot in SaveText array.
  1756. '                 Text$ MUST have lbound of 1 and NOT 0
  1757. '                 (see above comments about changes in V2.3)
  1758. '  StartTextRow%: starting row of text area (relative to window)
  1759. '  StartTextCol%: starting column of text area (relative to window)
  1760. '  EndTextRow%:   ending row of text area (relative to window)
  1761. '  EndTextCol%:   ending column of text area (relative to window)
  1762. '  CloseIcon%:    1=display a close icon; 0=no close icon
  1763. '                 [regardless of whether a close icon is displayed, the ESC
  1764. '                 key will always generate a close action]
  1765. '  ModeSw%:       Mode of window (effects how/if/when WinEvent returns
  1766. '                 control after an action has taken place)
  1767. '                (NEGATIVE value for mode will generate a shadowless window):
  1768. '                 1 = modeless window (normal). if modeless window has
  1769. '                    focus, user can click on any other visible window
  1770. '                    and it will be given focus by WinEvent. WinEvent will
  1771. '                    continue to process the new window until an action
  1772. '                    is taken in the current window.
  1773. '                 2 = modal window. if modal window has focus, any attempt
  1774. '                    to click on another window will be ignored by WinEvent.
  1775. '                    this type of window can be used to display a message,
  1776. '                    and force user to close the window before continuing
  1777. '                    (e.g., for error messages).
  1778. '                 3 = if this type window has focus, clicking on another
  1779. '                    window, or even the wallpaper, will cause WinEvent to
  1780. '                    return a close action (1). This can be used for menu
  1781. '                    windows that should be closed if user clicks somewhere
  1782. '                    else on the screen.
  1783. '                 4 = not valid for OpenScrollWindow (see BlankWin)
  1784. '
  1785. '
  1786. 'Values Returned:
  1787. '----------------
  1788. ' >0:  window opened successfully (window's number returned)
  1789. ' -1:  not enough storage for another new window.
  1790. '      [must increase the global parameter MaxWindows]
  1791. ' -2:  not enough room for window's rows (+1 for shadow) on screen
  1792. ' -3:  not enough room for window's columns (+2 for shadow) on screen
  1793. ' -4:  window's color attribute out of range (must be 0-15)
  1794. ' -5:  window's border color attribute out of range (must be 0-15)
  1795. ' -6:  invalid value for BorderType (must be 1, 2, -1, or -2)
  1796. ' -7:  text color attribute out of range (must be 0-15)
  1797. ' -8:  window not long enough (must be >=3)
  1798. ' -9:  window not wide enough (must be >=3)
  1799. '-10:  defined text area will not fit into window
  1800. '-11:  no room in SaveText array for another block of text
  1801. '      (increase value of MaxTextWins).
  1802. '-12:  invalid value for window mode (ModeSw) - must be 1 to 4
  1803. '
  1804.  
  1805. 'Notes:
  1806. '------
  1807. '  Internally, OpenScrollWindow calls BlankWin to open an empty window.
  1808. '
  1809. '  You MUST check to see if window opened successfully (return code>0)
  1810. '  before calling any other LangWin functions or routines.
  1811. '  Otherwise, you will either get errors (such as Illegal Function Call,
  1812. '  Subscript Out of Range, etc.) or process the previously opened
  1813. '  window by mistake.
  1814.  
  1815. '  OpenScrollWindow calls BlankWin which sets the global
  1816. '  variable AnyWinOpen to TRUE.
  1817. '  this can be used to control a DO/LOOP that executes WinEvent
  1818. '  as long as there is an open window on the screen. However, if an
  1819. '  information only window is open, then you must use another criteria to
  1820. '  end the DO/LOOP because the info only window will always be open.
  1821. '  In this case, termination should occur when a close action
  1822. '  occurs in the main window.
  1823.  
  1824. ' The Text$ array passed to OpenScrollWindow contains lines of text to be
  1825. ' displayed in a scrollable window. LBOUND(Text$) MUST be 1; otherwise
  1826. ' a run-time error will terminate your program when OpenScrollWindow
  1827. ' is called.
  1828.  
  1829. ' If your array of scrollable text is generated dynamically at run time and
  1830. ' its length could exceed MaxTextLines, then you MUST detect this condition
  1831. ' and design your program to handle it. OpenScrollWindow will only display
  1832. ' the first MaxTextLines in the string array (Text$) passed. The
  1833. ' MaxTextLines entry in the scrollable list
  1834. ' will be displayed as:     (Incomplete List)
  1835. ' So, your user will know that the complete list is not visible.
  1836. ' However, your program should detect this condition and give the user
  1837. ' the opportunity to see the missing entries.
  1838.  
  1839. ' To see if this condition occured, merely compare UBOUND(Text$)
  1840. ' to MaxTextLines. If UBOUND(Text$) > MaxTextLines, then part of the
  1841. ' Text$ array will not be visible in the scrollable text window.
  1842. ' In that case, you could offer the user an option to see more text,
  1843. ' loop, delete the first MaxTextLines from the Text$ array, and
  1844. ' open a new scrollable text window with the remaining lines.
  1845. ' You'd continue this process until the user had the opportunity to
  1846. ' see all of the original Text$ array. Another (easier) option is to
  1847. ' give the user the ability to set MaxTextLines at run-time by initializing
  1848. ' MaxTextLines from a parameter file. Of course, this opens the door
  1849. ' for abuse: the user could pick a value so large that the program
  1850. ' runs out of memory. I'll leave the actual solution to you!
  1851.  
  1852. ' Null lines in the list of scrollable text cannot be given focus. If you
  1853. ' scroll a list with null lines, the focus will disappear when you get to a
  1854. ' null line. This can be confusing to the end user. Unless it's absolutely
  1855. ' necessary, you should not include null lines in the Text$ array passed to
  1856. ' OpenScrollWindow. OpenScrollWindow will not display any null lines at the
  1857. ' end of the Text$ array. Null lines within the Text$ array will appear in
  1858. ' scrollable list, but as previously mentioned, the focus will disappear
  1859. ' when the user scrolls the highlight to one of these lines.
  1860.  
  1861.  
  1862. END FUNCTION
  1863.  
  1864. SUB RefreshScrollText.
  1865.  
  1866. 'Purpose:
  1867. '--------
  1868. '    Redisplay new scrollable text in the current window with focus
  1869. '    (the entire set of scrollable text is replaced).
  1870.  
  1871.  
  1872. '    New with V2.0
  1873. '    -------------
  1874.  
  1875. '    Modified in V2.3
  1876. '    ----------------
  1877. '    In previous versions of LangWin, if RefreshScrollText was called with
  1878. '    UBOUND(Text$) > the global variable MaxTextLines, a run-time error would
  1879. '    immediately terminate your program.
  1880.  
  1881. '    As of V2.3, if UBOUND(Text$) > MaxTextLines,
  1882. '    the scrollable text window will be redisplayed, but only lines 1
  1883. '    through MaxTextLines of the Text$ array will be scrollable. To let you
  1884. '    know that all of the Text$ array is not available in the scroll window,
  1885. '    the MaxTextLine entry will appear as:   (Incomplete List)
  1886. '    The original Text$ array will not be altered; Text$(MaxTextLine) remains
  1887. '    unchanged. The string "(Incomplete List)" only appears in the window's
  1888. '    scrollable list.
  1889. '
  1890.  
  1891. 'Routine Type:
  1892. '-------------
  1893. '  Subroutine.
  1894.  
  1895.  
  1896.  
  1897. 'Parameters:
  1898. '-----------
  1899. '     Text$   -  string array with new scrollable text to be displayed in the
  1900. '                current window with focus.
  1901. '                Text$ MUST have LBOUND of 1 and NOT 0
  1902.  
  1903.  
  1904. 'Notes:
  1905. '------
  1906.  
  1907. ' The Text$ array passed to RefreshScrollText contains lines of text to be
  1908. ' redisplayed in the current scrollable window. LBOUND(Text$) MUST be 1.
  1909. ' If this conditions is not met (i.e., LBOUND(Text$) <> 1, then
  1910. ' a run-time error will occur when RefreshScrollText is called.
  1911.  
  1912. ' If RefreshScrollText is called and the current window with focus does not
  1913. ' have scrollable text, then a run-time error will occur.
  1914.  
  1915. ' Null lines in the list of scrollable text cannot be given focus. If you
  1916. ' scroll a list with null lines, the focus will disappear when you get to a
  1917. ' null line. This can be confusing to the end user. Unless it's absolutely
  1918. ' necessary, you should not include null lines in the Text$ array passed to
  1919. ' RefreshScrollText. Null lines at the end of Text$ are eliminated.
  1920.  
  1921. ' RefreshScrollText works only on the current window. if you need to refresh
  1922. ' text and are not sure if the window to be refreshed is current, then the
  1923. ' following code can be used (assume you know that the variable win1
  1924. ' contains the number of the window which is to be refreshed):
  1925.  
  1926. '      IF IsWinOpen(win1,han) THEN       ' if win1 is open, return its handle
  1927. '         CALL NewFocusWindow(han)       ' make win1 current
  1928. '         CALL RefreshScrollText(Text$)  ' update the window
  1929. '      END IF
  1930.  
  1931. END SUB
  1932.  
  1933. SUB ReShowInputField.
  1934.  
  1935. 'Purpose:
  1936. '--------
  1937. '  Re-display contents of an Input Field after it has been changed.
  1938. '  Assumes that window containing the input field has focus.
  1939. '  If it does not, call NewFocusWindow first to give focus to appropriate
  1940. '  window.
  1941.  
  1942. '
  1943. 'Routine Type:
  1944. '-------------
  1945. '  Subroutine.
  1946. '
  1947. '
  1948. 'Parameters:
  1949. '-----------
  1950. '  Handle%:  handle of Input Field to be displayed
  1951. '
  1952. '
  1953. 'Notes:
  1954. '------
  1955. '  ButtonsText(Han) contains the text from the Input Field whose handle
  1956. '  is Han. If your program modifies this text, you must re-display it
  1957. '  in the current window (if you want the current window to reflect the
  1958. '  change made to ButtonsText(Han)). Call ReShowInputField(Han) to
  1959. '  accomplish this function.
  1960. '
  1961. '  See MakeInputField for additional details on creating an Input Field
  1962. '  and the handle assigned to each field.
  1963.  
  1964. END SUB
  1965.  
  1966. SUB ReShowPage.
  1967.  
  1968. 'Purpose:
  1969. '--------
  1970. '  Re-display all scrollable text lines that are visible in the current
  1971. '  window. Useful if you have made changes to several lines of scrollable
  1972. '  text and need to update the window. If window with scrollable text to
  1973. '  be re-displayed is not current, first call NewFocusWindow to give
  1974. '  focus to the appropriate window.
  1975.  
  1976. '
  1977. '
  1978. 'Routine Type:
  1979. '-------------
  1980. '  Subroutine.
  1981. '
  1982.  
  1983. 'V2.0 Changes:
  1984. '-------------
  1985. '   text array no longer needed as a parameter. text for all windows is
  1986. '   saved in SaveText array when window is opened.
  1987. '
  1988.  
  1989. 'Parameters:
  1990. '-----------
  1991. '  None.  (V2.0 change)
  1992. '
  1993. '
  1994. 'Notes:
  1995. '------
  1996. '  You might define a button that causes action to be taken on selected
  1997. '  lines of scrollable text (i.e., update all files whose names have been
  1998. '  previously "selected" by double-clicking on them). After taking the
  1999. '  necessary action, your code would toggle the "select" character in
  2000. '  every line of text from on to off (i.e., change an "X" to a blank).
  2001. '  After this has been done, the scrollable text that is visible in the
  2002. '  current window must be re-displayed to reflect these changes. Use the
  2003. '  ReShowPage routine to accomplish this function.
  2004. '
  2005. '  See ReShowText for details on re-displaying single lines of scrollable
  2006. '  text in the current window (i.e., after a text line has been double-
  2007. '  clicked and you change the contents of that text).
  2008. '  See WinEvent for details on responding to events from the current
  2009. '  window.
  2010. '
  2011. '  In general, you should not change the DIM of the scrollable text array
  2012. '  while its window is open. Nor should you use ReShowPage to re-display
  2013. '  a text array other than the one that was defined when the window was
  2014. '  originally opened.
  2015.  
  2016. END SUB
  2017.  
  2018. SUB ReShowText.
  2019.  
  2020. 'Purpose:
  2021. '--------
  2022. '  Re-display the currently highlighted scrollable text entry
  2023. '  after it has been changed (one line is re-displayed).
  2024. '  Assumes that window containing the scrollable text has focus.
  2025. '  If it does not, call NewFocusWindow first to give focus to appropriate
  2026. '  window.
  2027. '
  2028. '
  2029. 'Routine Type:
  2030. '-------------
  2031. '  Subroutine.
  2032. '
  2033.  
  2034. 'V2.0 Changes:
  2035. '-------------
  2036. '   text array no longer needed as a parameter. text for all windows is
  2037. '   saved in SaveText array when window is opened.
  2038. '
  2039. '
  2040. 'Parameters:
  2041. '-----------
  2042. '  none.     (v2.0 change)
  2043. '
  2044. '
  2045. 'Notes:
  2046. '------
  2047. '  If the currently highlighted line of scrollable text is changed by your
  2048. '  program in response to some event or process, then use ReShowText to
  2049. '  re-display the modified line of text in the current window. For
  2050. '  example, if you detect, via WinEvent, a double-click on a line of
  2051. '  scrollable text, and you want to mark that line as "selected" before
  2052. '  going back and waiting on another event, you could change a specific
  2053. '  character in the selected text line (i.e., change a blank to an X) and
  2054. '  re-display it with ReShowText. In this example, WinEvent would return a
  2055. '  value of 2 (signifying that a line of scrollable text was double-
  2056. '  clicked) and WinParms(CurWinPtr,15) would contain the index, in your
  2057. '  array of scrollable text, that was selected; that is:
  2058. '  Text$(WinParms(CurWinPtr,15)) was double-clicked. After making the
  2059. '  appropriate changes to the selected line in the Text$ array,
  2060. '  CALL ReShowText(Test$()) to re-display it in the visible window.
  2061. '
  2062. '  You might also have a button whose function is to take action on all
  2063. '  selected lines of scrollable text. After detecting that this button was
  2064. '  clicked, via WinEvent, and taking the necessary action, you would
  2065. '  change all the characters that had been set to denote selection
  2066. '  (say an X) back to a character that denotes no selection (say a blank)
  2067. '  and then re-display all lines of scrollable text that are currently
  2068. '  visible in the window (see ReShowPage).
  2069. '
  2070. '  See WinEvent for details on responding to events from the current
  2071. '  window.
  2072. '
  2073. '  In general, you should not change the DIM of the scrollable text array
  2074. '  while its window is open. Nor should you use ReShowPage to re-display
  2075. '  a text array other than the one that was defined when the window was
  2076. '  originally opened.
  2077.  
  2078. END SUB
  2079.  
  2080. SUB SetColor.
  2081.  
  2082. 'Purpose:
  2083. '--------
  2084. '  Set foreground/background color attributes. When using LangWin,
  2085. '  SetColor MUST be used instead of BASIC's COLOR command.
  2086. '
  2087. '
  2088. 'Routine Type:
  2089. '-------------
  2090. '  Subroutine.
  2091. '
  2092. '
  2093. 'Parameters:
  2094. '-----------
  2095. '  Foreg%:  foreground color attribute (0-15)
  2096. '  Backg%:  background color attribute (0-15)
  2097. '
  2098. '
  2099. 'Notes:
  2100. '------
  2101. '  LangWin uses BIOS interrupt 10h, function 10h, sub-function 03h to
  2102. '  disable blinking colors. This allows 16 attribute numbers for window
  2103. '  (background) colors (rather than just 8). However, with blinking
  2104. '  disabled, foreground/background attribute numbers MUST be translated
  2105. '  before calling BASIC's COLOR command. SetColor does this translation.
  2106. '  If BASIC's COLOR command is called without this translation, you will
  2107. '  get unexpected colors.
  2108. '
  2109. '  If you need to change colors in any program that uses LangWin's
  2110. '  routines, use SetColor just as you would use BASIC's COLOR command.
  2111.  
  2112. END SUB
  2113.  
  2114. SUB SetMousePos.
  2115.  
  2116. 'Purpose:
  2117. '--------
  2118. '  Sets the current position of the mouse pointer (in pixel coordinates).
  2119. '
  2120. '
  2121. 'Routine Type:
  2122. '-------------
  2123. '  Subroutine.
  2124. '
  2125. '
  2126. 'Parameters:
  2127. '-----------
  2128. '  Horiz%:  new horizontal pixel coordinate of mouse.
  2129. '  Vert%:   new vertical pixel coordinate of mouse.
  2130. '
  2131. '
  2132. 'Notes:
  2133. '------
  2134. '  This subroutine calls BIOS interrupt 33h, function 04h.
  2135. '
  2136. '  Horizontal/vertical coordinates set are in PIXELS. If you know the
  2137. '  new column/row position, use integer multiplication by width/depth of
  2138. '  character in pixels to get pixel coordinates.
  2139. '
  2140. '  Also see: GetMousePos and GetButtonPress
  2141.  
  2142. END SUB
  2143.  
  2144. SUB SetXLimit.
  2145.  
  2146. 'Purpose:
  2147. '--------
  2148. '  Set horizontal limits for mouse pointer.
  2149. '
  2150. '
  2151. 'Routine Type:
  2152. '-------------
  2153. '  Subroutine.
  2154. '
  2155. '
  2156. 'Parameters:
  2157. '-----------
  2158. '  MinX%:  minimum horizontal coordinate (in pixels)
  2159. '  MaxX%:  maximum horizontal coordinate (in pixels)
  2160. '
  2161. '
  2162. 'Notes:
  2163. '------
  2164. '  Use this routine to restrain mouse pointer to a specific
  2165. '  horizontal area. Current mouse pointer will automatically
  2166. '  be moved into the allowable area if necessary.
  2167. '
  2168. '  BIOS interrupt 33h, function 07h is used.
  2169. '
  2170. '  Also see: SetYLimit
  2171.  
  2172. END SUB
  2173.  
  2174. SUB SetYLimit.
  2175.  
  2176. 'Purpose:
  2177. '--------
  2178. '  Set vertical limits for mouse pointer.
  2179. '
  2180. '
  2181. 'Routine Type:
  2182. '  Subroutine.
  2183. '
  2184. '
  2185. 'Parameters:
  2186. '-----------
  2187. '  MinY%:  minimum vertical coordinate (in pixels)
  2188. '  MaxY%:  maximum vertical coordinate (in pixels)
  2189. '
  2190. '
  2191. 'Notes:
  2192. '------
  2193. '  Use this routine to restrain mouse pointer to a specific
  2194. '  vertical area. Current mouse pointer will automatically
  2195. '  be moved into the allowable area if necessary.
  2196. '
  2197. '  BIOS interrupt 33h, function 08h is used.
  2198. '
  2199. '  Also see: SetXLimit
  2200.  
  2201. END SUB
  2202.  
  2203. SUB ShowMouseCursor.
  2204.  
  2205. 'Purpose:
  2206. '--------
  2207. '  Displays the mouse cursor.
  2208. '
  2209. '
  2210. 'Routine Type:
  2211. '-------------
  2212. '  Subroutine.
  2213. '
  2214. '
  2215. 'Parameters:
  2216. '-----------
  2217. '  None.
  2218. '
  2219. '
  2220. 'Notes:
  2221. '------
  2222. '  This subroutine calls BIOS interrupt 33h, function 01h.
  2223. '
  2224. '  The mouse cursor must be hidden before writing anything to the screen.
  2225. '  Otherwise, any character written to the same position as the mouse
  2226. '  cursor will not be displayed. HideMouseCursor accomplishes this task.
  2227. '  ShowMouseCursor is then used to re-display the mouse cursor.
  2228. '
  2229. '  LangWin sets a global flag (HaveMouse) to true if mouse exists.
  2230. '  This flag should be tested before calling ShowMouseCursor:
  2231. '        IF HaveMouse THEN CALL ShowMouseCursor
  2232. '
  2233. '  Also see: HideMouseCursor, MouseExists, and InitMouse.
  2234.  
  2235. END SUB
  2236.  
  2237. FUNCTION ShowTitle.
  2238.  
  2239. 'Purpose:
  2240. '--------
  2241. '  Display a title bar, centered at the top of the current window.
  2242. '  If appropriate window to contain title does not have focus,
  2243. '  call NewFocusWindow to make it current.
  2244. '
  2245. '  V2.1 Changes: return code 1 eliminated, return code 4 added.
  2246.  
  2247.  
  2248. 'Routine Type:
  2249. '-------------
  2250. '  Function.
  2251. '
  2252. '
  2253. 'Parameters:
  2254. '-----------
  2255. '  Title$:   string with title
  2256. '  Foreg%:   foreground color attribute (0-15)
  2257. '  Backg%:   background color attribute (0-15)
  2258. '
  2259. '
  2260. 'Return Values:
  2261. '--------------
  2262. '  0:  title successfully displayed
  2263. '  2:  background color attribute invalid (must be 0-15)
  2264. '  3:  foreground color attribute invalid (must be 0-15)
  2265. '  4:  not enough storage for another title (new with V2.1)
  2266. '      [must increase value of global parameter MaxButtons]
  2267.  
  2268. 'Notes:
  2269. '------
  2270. '   With LangWin V2.1, return code 1 is no longer used (this return
  2271. '   code used to indicate that the title was too wide for the window).
  2272. '   If the title is too wide, it will be truncated, and code 0 returned.
  2273.  
  2274. '   Also with LangWin v2.1, resizing has been implemented. Title data is
  2275. '   saved in data structures so it can be re-displayed when a window is
  2276. '   resized. Code 4 is returned if there is no more room in the data
  2277. '   structures (i.e., ButtonsText and ButtonsData). In this case, you'll
  2278. '   need to increase the value of the global variable MaxButtons.
  2279. END FUNCTION
  2280.  
  2281. FUNCTION ShowWinText.
  2282.  
  2283. 'Purpose:
  2284. '--------
  2285. '  Display a line of static (non-scrollable) text in current window.
  2286. '  If appropriate window to contain text is not current, first call
  2287. '  NewFocusWindow to make it current.
  2288.  
  2289. '
  2290. 'Routine Type:
  2291. '-------------
  2292. '  Function:
  2293. '
  2294. '
  2295. 'Parameters:
  2296. '-----------
  2297. '  Row%:        row where text will be placed
  2298. '  Col%:        starting column
  2299. '  Foreg%:      foreground color attribute (0-15)
  2300. '  Text$        string with static text to be displayed
  2301. '
  2302. '
  2303. 'Return Values:
  2304. '--------------
  2305. '   0:  text successfully displayed
  2306. '  -1:  text extends beyond current window
  2307. '  -3:  foreground color not valid (must be 0-15)
  2308. '  -4:  not enough storage for to save this text (new with V2.1)
  2309. '       [must increase value of global parameter MaxButtons]
  2310. '
  2311. '
  2312. 'Notes:
  2313. '------
  2314. '  Row and column are relative to the current window.
  2315. '  Row 0, Column 0, represent the first row/column in the window,
  2316. '  regardless of where the window is located on the screen
  2317. '  (first /last row and column contain the window's border).
  2318. '  Window text will not be displayed if it would extend beyond boundaries
  2319. '  of the current window (on the border is ok).
  2320.  
  2321. '  To display numeric values in a window, use STR$(number) in the Text$
  2322. '  parameter. For example:
  2323. '  CALL ShowWinText(2, 3, 15, "Number of Wigits: " + STR$(NumWig))
  2324.  
  2325. '  With LangWin v2.1, resizing has been implemented. Static text data is
  2326. '  saved in data structures so it can be re-displayed when a window is
  2327. '  resized. Code -4 is returned if there is no more room in the data
  2328. '  structures (i.e., ButtonsText and ButtonsData). In this case, you'll
  2329. '  need to increase the value of the global variable MaxButtons.
  2330.  
  2331. ' Static text created by ShowWinText can be modified/changed by calling
  2332. ' ShowWinText again, with the same row/column but new text. This is
  2333. ' acceptable when only a few updates are needed. However, if the static text
  2334. ' is modified based upon some user action (like a button click), then there
  2335. ' is no way to determine the number of times the text will be modified. Each
  2336. ' time ShowWinText is called, the text is saved in LangWin's data structures
  2337. ' (ButtonsText and ButtonsData). These structures have a finite dimension
  2338. ' (MaxButtons). Each call to ShowWinText requires a new entry in the data
  2339. ' structures. Thus, repeated calls to modify text can exhaust all available
  2340. ' slots. In this case, the result would be that subsequent calls to create
  2341. ' objects (either new buttons, input fields, check boxes, or static text)
  2342. ' will fail and the object will not appear. Closing a window will free all
  2343. ' slots occupied by its objects. Increasing the value of MaxButtons will make
  2344. ' more slots available. However, neither of these is a good solution. A
  2345. ' better solution is to re-use the same slot whenever existing static text is
  2346. ' modified. All that is needed is to first determine the slot number (handle)
  2347. ' of the static text, then to update the contents of the existing slot and
  2348. ' re -display it.
  2349.  
  2350. ' Since ShowWinText returns an error code and not the handle of the slot used
  2351. ' to store text, you'll need to find and save the handle number in order to
  2352. ' later modify its contents. The best way to do this is to use ShowWinText to
  2353. ' temporarily place some specific text into the data structures, then
  2354. ' manually scan the data structure until you find the specific text. The
  2355. ' following code will accomplish these tasks:
  2356.  
  2357.  
  2358. '        x = ShowWinText(r, c, colr, "SOME UNIQUE TEXT")
  2359. '        ' the above will place "SOME UNIQUE TEXT" at row=r, column=c in the
  2360. '        ' current window using color=colr. the string "SOME UNIQUE TEXT"
  2361. '        ' will also be placed into the next available slot in ButtonsText
  2362. '        IF x < 0 THEN
  2363. '           ' if error condition, process it
  2364. '           END
  2365. '        END IF
  2366. '
  2367. '        thandle = -999   ' set a default value for the handle
  2368. '
  2369. '        ' now search ButtonsText for the specific text string
  2370. '        FOR i = 1 TO MaxButtons
  2371. '            IF ButtonsText(i) = "SOME UNIQUE TEXT" THEN
  2372. '                thandle = i ' save handle number
  2373. '                EXIT FOR    ' quit serach
  2374. '            END IF
  2375. '        NEXT
  2376. '
  2377. '        ' just in case the "impossible" happens
  2378. '        IF thandle = -999 THEN
  2379. '                ' process the error
  2380. '                END
  2381. '        END IF
  2382.  
  2383. ' At this point, the variable:  thandle  points to the slot in LangWin's data
  2384. ' structures that contains the temporary static text. The screen itself
  2385. ' displays the temporary text at the designated row/column. Now, you must
  2386. ' replace the temporary text with the initial value of the static text (using
  2387. ' the same slot in the data structures) and display this text on the screen.
  2388. ' The following code will accomplish these tasks:
  2389.  
  2390. '        a$ = "initial contents of static text field"
  2391. '        ButtonsText(thandle) = a$        ' update text in data structure
  2392. '        CALL ReShowInputField(thandle)   ' redisplay text on screen
  2393. '        ButtonsData(thandle, 4) = LEN(a$)' update length of text area
  2394.  
  2395. ' You might ask: why is the length of the text in LangWin's data structure
  2396. ' updated AFTER the text is displayed? Glad you asked that question!
  2397. ' ReShowInputField (which is really meant to redisplay the contents of an
  2398. ' input field after it has been modified, but will also redisplay static
  2399. ' text) first clears the entire contents of the area, then displays the
  2400. ' new text. The length of the area to clear is obtained from the data
  2401. ' structure. So, if the length of the new text was smaller than the previous
  2402. ' text, and the new (smaller) length was first placed into the data structure,
  2403. ' then only the smaller area would cleared prior to displaying the new text.
  2404. ' Any characters from the previous (longer) text beyond the end of the new
  2405. ' (smaller) text would remain on the screen. By calling ReShowInputField
  2406. ' before the length is updated, the length of the area cleared will
  2407. ' correspond to the the current text.
  2408.  
  2409. ' Later in your program, when you determine that new static text must be
  2410. ' placed into the window at the same position as the old text, the following
  2411. ' code can be used:
  2412.  
  2413. '        a$ = "new contents of static text field"
  2414. '        ButtonsText(thandle) = a$        ' update text in data structure
  2415. '        CALL ReShowInputField(thandle)   ' redisplay text on screen
  2416. '        ButtonsData(thandle, 4) = LEN(a$)' update length of text area
  2417.  
  2418. ' These techniques can be used with any number of static text entries. You'll
  2419. ' just need to save each handle in a unique variable name.
  2420.  
  2421.  
  2422.  
  2423. END FUNCTION
  2424.  
  2425. SUB WaitTicks.
  2426.  
  2427. 'Purpose:
  2428. '--------
  2429. '  A timed delay similar to SLEEP but more granular.
  2430. '
  2431. '
  2432. 'Routine Type:
  2433. '-------------
  2434. '  Subroutine.
  2435. '
  2436. '
  2437. 'Parameters:
  2438. '-----------
  2439. '  Ticks%:  number of timer ticks to "sleep".
  2440. '           this parameter MUST be between 0 and 255.
  2441. '           each "tick" is approximately (1/18.2) seconds.
  2442. '
  2443. 'Notes:
  2444. '------
  2445. '  Address 0040:006Ch is a 32-bit timer that is incremented approximately
  2446. '  18.2 times per second. This routine examines the low byte of this
  2447. '  timer, and waits for the specified number of increments (ticks)
  2448. '  to elapse before returning. While any value up to 255 is valid for the
  2449. '  input parameter (i.e., the maximum value of a byte), in practice, you
  2450. '  should only need input values from 0 - 18.
  2451. '  For values greater than 18 (i.e., to wait more than one second),
  2452. '  use the SLEEP function instead (whose granularity is in seconds).
  2453. '
  2454. '  Use WaitTicks if you need to delay for some period less than a second.
  2455. '  It is also useful if you need your code to wait a consistent amount of
  2456. '  time regardless of what speed/model CPU it runs on. A FOR/NEXT delay
  2457. '  loop will not produce consistent delays across different speed CPUs.
  2458.  
  2459. END SUB
  2460.  
  2461. FUNCTION WinEvent.
  2462.  
  2463. 'Purpose:
  2464. '--------
  2465. '  Wait for an event to occur in the current window.
  2466. '  This routine should be called AFTER opening a window and
  2467. '  any associated buttons, text, input fields, check boxes, etc.
  2468.  
  2469. '  This routine will automatically handle mouse clicks on other underlying
  2470. '  visible windows. If appropriate (see ModeSw in BlankWindow and
  2471. '  OpenScrollWindow), the underlying window clicked will be given focus.
  2472. '  When control is returned from WinEvent, its return code will be the
  2473. '  current window's number. In addition, WinEvent's action parameter
  2474. '  will be set to one of the following values:
  2475. '  1) close was selected; 2) scrollable text entry selected;
  2476. '  or 3) push button selected. user also can define global hot keys and
  2477. '  corresponding action codes returned when key is hit.
  2478. '
  2479. '  If an "information only" window has been opened (i.e., one for which
  2480. '  there are no events that can occur), then WinEvent need not be called.
  2481. '  The information only window, however, should be closed when it is no
  2482. '  longer needed.
  2483. '
  2484. 'Routine Type:
  2485. '-------------
  2486. '  Function.
  2487. '
  2488.  
  2489. 'V2.0 Changes:
  2490. '-------------
  2491. '   string array with scrollable text no longer needed as parameter.
  2492. '   parameter is an action code for event in the window (see below).
  2493. '   value of WinEvent returned is either -1 (error occurred) or
  2494. '   the window's number that is current (i.e., that generated the action).
  2495.  
  2496. '   WinEvent no longer locks the mouse on the current window.
  2497. '   User can select other visible windows.
  2498.  
  2499. 'V2.3 Changes:
  2500. '-------------
  2501. '   "Time Out" feature added. If the action% parameter passed is -999, then
  2502. '   WinEvent will return control to the calling program after 0.5 seconds if
  2503. '   no events are detected (see Notes for more details).
  2504.  
  2505. 'Parameters:
  2506. '-----------
  2507. '   action%:  a return code representing the action that occurred in the
  2508. '             current win (if action% is set to -999 upon entry, the "time
  2509. '             out" feature will be enabled).
  2510.  
  2511. '             1 => close event (ESC key, close button double clicked,
  2512. '                  or Mode 2 window was current and user clicked on
  2513. '                  some other window or wallpaper).
  2514.  
  2515. '             2 => scrollable text selected (double click in scrollable text,
  2516. '                  or ENTER hit while a specific line of scrollable text had
  2517. '                  FOCUS and no other buttons had FOCUS).
  2518. '                    SaveText(i,j) is text selected; where
  2519. '                       i=WinParms(CurWinPtr,18)
  2520. '                       j=WinParms(CurWinPtr,15)
  2521.  
  2522. '             3 => button selected (double click on push button or ENTER hit
  2523. '                  while a specific button had FOCUS).
  2524. '                    handle of button = WinParms(CurWinPtr,16)
  2525. '                    ButtonsText(handle) contains the button's text
  2526. '                                 (or null if button is not active)
  2527. '                    ButtonsData(handle,i) contains info on button
  2528.  
  2529. '           >=4 => user defined hot keys can be associated with an action
  2530. '                  code that is returned whenever a hot key is hit.
  2531.  
  2532. '          -999 => if action% is set to -999 upon entry to WinEvent, then the
  2533. '                  "time out" feature will be enabled. this feature will cause
  2534. '                  control to be returned to the calling program if no events
  2535. '                  are detected within 0.5 seconds. see Notesd for additional
  2536. '                  details.
  2537.  
  2538. 'Values Returned:
  2539. '----------------
  2540. '   -1:  error occurred
  2541. '   >0:  window number with FOCUS when event occurred.
  2542.  
  2543.  
  2544. '
  2545. 'Notes:
  2546. '------
  2547. '
  2548. '  WinEvent is the workhorse of LangWin. After opening a window(s) and
  2549. '  defining buttons, scrollable text, check boxes, input fields, etc., you
  2550. '  must call WinEvent to wait for an event/action to occur.
  2551. '  WinEvent returns two important values: the WinEvent function returns
  2552. '  the window's number that had FOCUS when the event occurred. The action
  2553. '  parameter defines what event took place in the current window.
  2554.  
  2555. '  WinEvent processes all GUI functions in all visible windows. Some events
  2556. '  are handled entirely within WinEvent (i.e., mouse movements, scrolling,
  2557. '  changing FOCUS among windows or items in the window, clicking/un-clicking
  2558. '  check boxes, entering values into input fields). Other events will cause
  2559. '  WinEvent to return control to your program.
  2560.  
  2561. '  There are 3 pre-defined generic events/actions that will cause WinEvent to
  2562. '  return control to the calling program: the close icon (upper right) was
  2563. '  double clicked (or ESC hit), a line of scrollable text was double
  2564. '  clicked (or ENTER was hit while the scrollable text had FOCUS and no
  2565. '  other button had FOCUS), or a push button was single clicked (or ENTER
  2566. '  was hit while the button had FOCUS). You can also define Hot Keys, and
  2567. '  corresponding WinEvent action codes. Each user-defined Hot Key is also
  2568. '  considered a window event. When a Hot Key is selected, WinEvent returns
  2569. '  control to the calling program with the corresponding user-defined
  2570. '  action code for that Hot Key.
  2571. '
  2572. '  The value of the WinEvent function corresponds to the window's number
  2573. '  that generated the above action.
  2574. '  First, an explanation of the difference between a window's number and its
  2575. '  handle is necessary. When a window is opened (BlankWindow or
  2576. '  OpenScrollWindow), it is given a unique number. Data for the window is
  2577. '  stored in several arrays, and the index to these arrays is called the
  2578. '  window's handle (CurWinPtr is a global variable containing the handle
  2579. '  of the window currently in FOCUS). The slots of the arrays are re-used
  2580. '  as windows are opened and closed, so the window's handle cannot be used
  2581. '  to uniquely determine the window. The window's number is a sequential
  2582. '  value which is never re-used. Thus handle number 3 might point to data
  2583. '  for window number 6 at one point, and after that window is closed and
  2584. '  another is opened, handle number 3 could then point to data for window
  2585. '  number 7. This is why WinEvent returns the window's number that generated
  2586. '  the event. If it returned the handle, you could not be sure exactly which
  2587. '  window was currently pointed to by the handle (and thus how to handle the
  2588. '  action from that window). WinNum is a cross reference array containing
  2589. '  window numbers. WinNum(i) contains the window number that corresponds to
  2590. '  handle i.
  2591.  
  2592. '  In general, WinEvent should be placed at the top of a DO/LOOP. After
  2593. '  returning control to your program, test WinEvent's value to determine
  2594. '  which window number had FOCUS, then for each possible window number that
  2595. '  your program could open, process the particular event/action.
  2596. '  You can determine if any information was entered into input fields,
  2597. '  if check boxes were selected, if buttons were clicked, etc. in the
  2598. '  current window.
  2599.  
  2600. '  the global variable AnyWinOpen can be used to control the DO/LOOP.
  2601. '  It will be TRUE as long as there is an open window on the screen. However,
  2602. '  if an information only window is open (i.e., one with text only where
  2603. '  no events could occur), then you must use another criteria
  2604. '  to end the DO/LOOP because the info only window will always be open.
  2605. '  In this case, termination should occur when a close action
  2606. '  occurs in the main window.
  2607.  
  2608. '  Prototype code would look like this:
  2609.  
  2610. '  open some windows and make buttons, etc.
  2611. '  window numbers saved in variables win1 and win2
  2612.  
  2613. '  win1=OpenScrollWindow(......)
  2614. '     make some buttons
  2615. '  win2=OpenScrollWindow(....)
  2616. '     make some buttons
  2617.  
  2618. '  DO WHILE AnyWinOpen
  2619. '    wnum=WinEvent(action)  ' wnum= win number; action= action code
  2620. '    SELECT CASE wnum
  2621.  
  2622. '    CASE win1
  2623. '       SELECT CASE action
  2624. '       CASE 1 ' close
  2625. '           process the close action
  2626. '       CASE 2 ' text selected
  2627. '           process the selected text
  2628. '       CASE 3 ' button clicked
  2629. '           process the button
  2630. '       END SELECT
  2631.  
  2632. '    CASE win2
  2633. '       SELECT CASE action
  2634. '       CASE 1 ' close
  2635. '           process the close action
  2636. '       CASE 2 ' text selected
  2637. '           process the selected text
  2638. '       CASE 3 ' button clicked
  2639. '           process the button
  2640. '       END SELECT
  2641.  
  2642. '    END SELECT
  2643. '  LOOP
  2644.  
  2645. '
  2646. '  A brief description on how to process window events will be
  2647. '  given here. Refer to LANGWIN.DOC and the sample programs distributed
  2648. '  with LangWin for more details.
  2649. '
  2650. '  Three data structures contain information necessary to process
  2651. '  window events: WinParms(CurWinPtr,i):   data on current window
  2652. '                 ButtonsData(Handle,i):   data on all buttons/fields
  2653. '                 ButtonsText(Handle):     text contents of buttons/fields
  2654. '
  2655. '                 CurWinPtr: is a global parameter maintained by LangWin.
  2656. '                        It always points to the current window's handle.
  2657. '                 Handle: is the value assigned to the button/box/field when
  2658. '                        it was opened (see: MakePushButton, MakeCheckBox,
  2659. '                        and MakeInputField)
  2660. '                 i:  represents an index into the structure
  2661.  
  2662. '  Suggested processing for the various actions/events returned by WinEvent:
  2663. '
  2664. '  CLOSE EVENT (code = 1):
  2665. '      Not much to do here.
  2666. '      CALL CloseWindow to close the current window.
  2667. '      Then continue processing the DO/LOOP with WinEvent as long
  2668. '      as other windows are still open.
  2669. '
  2670. '  SCROLLABLE TEXT EVENT (code = 2):
  2671. '      A line of scrollable text was selected.
  2672. '           SaveText(i,j) contains the selected text; where
  2673. '                  i=WinParms(CurWinPtr,18)
  2674. '                  j=WinParms(CurWinPtr,15)
  2675. '
  2676. '      Process the selected text line as appropriate.
  2677. '      For example, if the contents of SaveText(i,j) must be modified (i.e.,
  2678. '      a "select" character toggled), then update the text line as necessary.
  2679. '      After updating the text, CALL ReShowText to
  2680. '      re-display the new text in the current window. The scrollable
  2681. '      text could consist of parameters that, when selected, will cause
  2682. '      additional processing (and maybe additional windows to be open).
  2683. '      Use the values of i and j to determine which line in your scrollable
  2684. '      parameter list was selected (and thus what additional processing
  2685. '      and/or windows are needed).
  2686. '
  2687. '      After all processing has been completed for the text line selected,
  2688. '      continue with the WinEvent loop.
  2689.  
  2690.  
  2691. '
  2692. '  PUSH BUTTON EVENT (code = 3):
  2693. '      A specific Push Button was selected. WinParms(CurWinPtr,16)
  2694. '      contains the Handle for that button. Using that Handle, you
  2695. '      should compare it to the handles of all buttons created for the given
  2696. '      window that generated the event (all button handles assigned by
  2697. '      MakeCheckBox and MakeInputField should be saved in variables).
  2698. '      When you find a match, process the button action as necessary.
  2699.  
  2700. '      Prototype might look like this (assume button1 & button2 variables
  2701. '      contain handles of buttons created for the window):
  2702.  
  2703. '      CASE 3 ' button clicked
  2704. '         handle=WinParms(CurWinPtr,16)
  2705. '         SELECT CASE handle
  2706. '         CASE button1
  2707. '           code to process button1
  2708. '         CASE button2
  2709. '           code to process button2
  2710. '         END SELECT
  2711.  
  2712. '      You may need to determine which text line had FOCUS when the Push
  2713. '      Button was selected, and you may need to determine if any Input
  2714. '      Fields or Check Boxes were modified prior to the Push Button being
  2715. '      selected.
  2716. '
  2717. '      If WinParms(CurWinPtr,15) contains a -1, then no scrollable text
  2718. '      exists in the current window. Otherwise SaveText(i,j) had FOCUS
  2719. '      when the button was selected. Where:
  2720. '                  i=WinParms(CurWinPtr,18)
  2721. '                  j=WinParms(CurWinPtr,15)
  2722.  
  2723. '      To determine if any Input Field was modified, examine the contents
  2724. '      of all Input Fields in the given window using the handles saved
  2725. '      when you created the Input Field. Knowing the previous contents
  2726. '      of the Input Field, and its handle, test the value of
  2727. '      ButtonsText(handle). Take appropriate action if Input Field
  2728. '      was updated. If your program modifies an input field, then CALL
  2729. '      ReShowInputField to re-display the new Input Field in the current
  2730. '      window.
  2731.  
  2732. '      To determine the state of any Check Boxes in the current window, use
  2733. '      its Check Box handle (saved when you created the check boxes) and
  2734. '      examine ButtonsData(Handle,7). If this is a 1, then the Check Box
  2735. '      corresponding to Handle was not set. If this is a 0, then the box was
  2736. '      set. Do all necessary processing based upon the state of Check Boxes.
  2737. '
  2738. '      After all processing has been completed for the button selected,
  2739. '      continue with the WinEvent loop.
  2740.  
  2741.  
  2742.  
  2743. '  Calling WinEvent with action% set to -999 will enable the "time out"
  2744. '  feature. This feature will cause WinEvent to return control to the
  2745. '  calling program if no events are detected after 0.5 seconds. This
  2746. '  can be used to implement an "interrupt" button for long running tasks.
  2747.  
  2748. 'In order to interrupt a long running task, place the task in a loop with a
  2749. 'call to WinEvent (with time out feature enabled). Each time through the loop,
  2750. 'some portion of the long running task is completed (like reading one record
  2751. 'from a large file, scanning one directory, whatever portion of the overall
  2752. 'task that is appropriate). After completing a portion of the long running
  2753. 'task, call WinEvent with the time out feature. After the call to WinEvent,
  2754. 'determine what (if any) event occurred. If the event was a click on your
  2755. 'interrupt button, exit the loop that processed the long running task. If no
  2756. 'event occurred (i.e., WinEvent timed out after 0.5 seconds), then loop and
  2757. 'perform more work on the long running task.
  2758.  
  2759. 'Here's some pseudo code. Assume this code gets control when a "start" button
  2760. 'is clicked to initiate the long running task. Also assume that prior to this
  2761. 'point, a MODAL window was opened with start and interrupt buttons for the
  2762. 'long running task. Finally, assume that the long running task is to read all
  2763. 'records from a file.
  2764.  
  2765. '        CASE StartButton
  2766. '            deactivate "start" button (don't need it now)
  2767. '            activate "interrupt" button (assume it was previously inactive)
  2768. '            open a file (assume the long running task is to read a file)
  2769.  
  2770. '            ' process long running task
  2771. '            DO
  2772. '                read a record (assume the long running task is to read a file)
  2773. '                update screen to show some kind of progress
  2774. '                if EOF then EXIT DO  ' see if task is done
  2775. '                act=-999             ' to activate time out feature
  2776. '                wn=WinEvent(act)     ' get an action or time out
  2777. '            LOOP UNTIL interrupt button action detected
  2778.  
  2779. '            ' long running task completed or interrupted
  2780.             
  2781. '            deactivate "interrupt" button (not needed now)
  2782. '            activate the "start" button (if it's needed)
  2783. '            close file
  2784. '            process the data
  2785. '            close the current window (if it's no longer needed)
  2786.  
  2787.  
  2788. 'Note that you should not attempt to do too much work in your loop before
  2789. 'periodically giving control to WinEvent (to see if the interrupt button was
  2790. 'clicked). WinEvent is not aware of mouse clicks made before it is called
  2791. 'because it must hide and re-show the mouse cursor during initialization
  2792. '(which causes the mouse driver to zero the mouse press counter). Thus, if you
  2793. 'do a lot of processing before calling WinEvent, your user could have been
  2794. 'attempting to click the interrupt button for awhile with no response. You'll
  2795. 'have to experiment, and tune your code so that it gets back to WinEvent
  2796. 'quickly. If you notice that the interrupt button needs to be clicked very
  2797. 'frequently before it is recognized, then the cause is probably due to an
  2798. 'excessive amount of time consumed by your task in between iterations of the
  2799. 'loop where WinEvent is called.
  2800.  
  2801. 'I strongly recommend that the window you open, with buttons to start and
  2802. 'interrupt the long running task, be MODAL (i.e., only events in that window
  2803. 'will be recognized by WinEvent, events in other windows will be ignored). The
  2804. '"in-line" call to WinEvent (in the loop that processes your long running task)
  2805. 'will restrict the events recognized by your program to just those that you
  2806. 'explicitly test after returning from WinEvent (the code you have elsewhere
  2807. 'in your program to handle other buttons in other windows will not be given
  2808. 'control). If the window with the start and interrupt buttons is not modal,
  2809. 'then your user will be able to mouse to other windows, make them active, and
  2810. 'click their buttons. This will have visual effects (active windows will move
  2811. 'to the top, clicked buttons will move); however, unless explicit code to
  2812. 'handle these events (in other windows) is included in your loop with the long
  2813. 'running task, the clicks on other buttons will be ignored. This will confuse
  2814. 'your user. By making the window with the start and interrupt buttons modal,
  2815. 'your user will not be able to mouse to another window to make it active, and
  2816. 'clicking objects on other windows will show no visual effect.
  2817.  
  2818. 'See SAMPLE05.BAS for an example of the technique for using WinEvent's time
  2819. 'out feature to implement an interrupt button.
  2820.  
  2821. END FUNCTION
  2822.  
  2823.